Compare commits
133 Commits
curl-7_12_
...
pre-aifix
Author | SHA1 | Date | |
---|---|---|---|
![]() |
818aed35e2 | ||
![]() |
2ed524f07e | ||
![]() |
5f1eefd03f | ||
![]() |
522b4d7576 | ||
![]() |
d6dcb08407 | ||
![]() |
806c756a2d | ||
![]() |
2494701347 | ||
![]() |
1c10272e15 | ||
![]() |
0badcf381a | ||
![]() |
35558e6bd7 | ||
![]() |
7659747e6f | ||
![]() |
53189fb2d7 | ||
![]() |
450c178d77 | ||
![]() |
a20eb6df1b | ||
![]() |
d73425061a | ||
![]() |
0051d5ac88 | ||
![]() |
76920413d9 | ||
![]() |
44d9a8ba4e | ||
![]() |
38dc548a87 | ||
![]() |
dca6386234 | ||
![]() |
2a701a1aac | ||
![]() |
0cb297abc9 | ||
![]() |
821a23535b | ||
![]() |
bc80599178 | ||
![]() |
941374b573 | ||
![]() |
1886893d66 | ||
![]() |
7291772b1f | ||
![]() |
8e28721057 | ||
![]() |
8d2120566e | ||
![]() |
67341c4cbe | ||
![]() |
f8188ddfee | ||
![]() |
29c546b426 | ||
![]() |
0d259b898b | ||
![]() |
c136b80af5 | ||
![]() |
83b87d53c1 | ||
![]() |
1e99f1ee41 | ||
![]() |
d7fe136d54 | ||
![]() |
cd7a0f829f | ||
![]() |
cf3f1ef284 | ||
![]() |
a737864a1c | ||
![]() |
c68a6805b3 | ||
![]() |
bd3d5a17b4 | ||
![]() |
d4b577114b | ||
![]() |
713effb6e4 | ||
![]() |
b92e2ab6b1 | ||
![]() |
05baf94b43 | ||
![]() |
a76288b99a | ||
![]() |
557e95c0a3 | ||
![]() |
0a83fa90bb | ||
![]() |
daeb143177 | ||
![]() |
9f752120c0 | ||
![]() |
80a1e972fc | ||
![]() |
5e65d48ffa | ||
![]() |
752ef08141 | ||
![]() |
070e0e8b0a | ||
![]() |
2ed0728cef | ||
![]() |
a79b9e9d4a | ||
![]() |
24572daccc | ||
![]() |
1770563fff | ||
![]() |
4cd96483f6 | ||
![]() |
8f1783b8a7 | ||
![]() |
be72eaa327 | ||
![]() |
61bded1d82 | ||
![]() |
4b3937373a | ||
![]() |
08bf0907d4 | ||
![]() |
eb044f8787 | ||
![]() |
8d0c77403c | ||
![]() |
601062455c | ||
![]() |
5be788ba36 | ||
![]() |
281559b31b | ||
![]() |
ef1aa4e5e9 | ||
![]() |
7b7ac04895 | ||
![]() |
60f5b2b275 | ||
![]() |
c0f9d7fdb7 | ||
![]() |
fc4d6f73a6 | ||
![]() |
295169f9d9 | ||
![]() |
1a3797a699 | ||
![]() |
977e106924 | ||
![]() |
8d76d4016d | ||
![]() |
9f92657f76 | ||
![]() |
9f341f9ce5 | ||
![]() |
2098871509 | ||
![]() |
3d00c86f4c | ||
![]() |
90037b85d1 | ||
![]() |
6ec145d4b4 | ||
![]() |
40a58c392f | ||
![]() |
9733cd59bb | ||
![]() |
b3caf7bfa8 | ||
![]() |
23fbb89805 | ||
![]() |
bd1adaf7ea | ||
![]() |
0c9e23fc0c | ||
![]() |
f091ce64ac | ||
![]() |
55a69ebea6 | ||
![]() |
d6b3850562 | ||
![]() |
80197cf493 | ||
![]() |
8ee564c216 | ||
![]() |
5bfeb60a83 | ||
![]() |
1ab4a2f870 | ||
![]() |
2a627059ac | ||
![]() |
3f739acf24 | ||
![]() |
d3454ceb94 | ||
![]() |
59695c05b1 | ||
![]() |
f0969c9692 | ||
![]() |
18dd8154e2 | ||
![]() |
4c58797607 | ||
![]() |
d620f1e529 | ||
![]() |
e0b436f8e1 | ||
![]() |
e99d1e97de | ||
![]() |
1fb74b4fa2 | ||
![]() |
473f6ea9f0 | ||
![]() |
0b04c52119 | ||
![]() |
8383945acc | ||
![]() |
fce9d51122 | ||
![]() |
7c3ee84295 | ||
![]() |
a8db25f48b | ||
![]() |
20705ca311 | ||
![]() |
af33c6b549 | ||
![]() |
2b8775dff7 | ||
![]() |
ea81dd9e2e | ||
![]() |
7dcb102733 | ||
![]() |
aa0e32060e | ||
![]() |
2e8f37aca5 | ||
![]() |
195d769c4b | ||
![]() |
70f08b5baa | ||
![]() |
9e987ac6a2 | ||
![]() |
de03f172ad | ||
![]() |
0078944486 | ||
![]() |
d3f796ac59 | ||
![]() |
3d38080d54 | ||
![]() |
fe07962f9c | ||
![]() |
938a72b2db | ||
![]() |
a8827b1ed6 | ||
![]() |
ff40cd71ac |
145
CHANGES
145
CHANGES
@@ -6,6 +6,151 @@
|
||||
|
||||
Changelog
|
||||
|
||||
Daniel (22 June 2004)
|
||||
- David Cohen pointed out that RFC2109 says clients should allow cookies to
|
||||
contain least 4096 bytes while libcurl only allowed 2047. I raised the limit
|
||||
to 4999 now and made the used buffer get malloc()ed instead of simply
|
||||
allocated on stack as before. Extended test case 46 to include a cookie with
|
||||
very huge content to verify the fix.
|
||||
|
||||
- G<>nter Knauf fixed getdate.y to remove a few warnings. I removed the
|
||||
ifdef'ed test we never ever use anyway.
|
||||
|
||||
- Gisle Vanem fixed the certificate wildcard checks to support a '*'-letter
|
||||
anywhere in the wildcard string, support multiple '*'-letters in the
|
||||
wildcard and to allow the '*'-letter to match a string that includes a dot.
|
||||
|
||||
Daniel (21 June 2004)
|
||||
- testcurl.sh is now removed completely, tests/testcurl.pl is the script to
|
||||
use when autobuilding curl!
|
||||
|
||||
- Kjetil Jacobsen brought my attention to the fact that you cannot properly
|
||||
abort an upload with the readfunction callback, since returning 0 or -1 only
|
||||
stops the upload and libcurl will continue waiting for downloaded data and
|
||||
the server often waits for the rest of the upload data to arrive.
|
||||
|
||||
Thus, I've now added the ability for read callbacks to return
|
||||
CURL_READFUNC_ABORT to abort an upload from a read callback. This will stop
|
||||
the transfer immediately with a CURLE_ABORTED_BY_CALLBACK return code.
|
||||
|
||||
Test case 513 was added to verify that it works. I had to improve the test
|
||||
HTTP server too to dump the request to a file even when the client
|
||||
disconnects prematurely.
|
||||
|
||||
Daniel (19 June 2004)
|
||||
- Luca Alteas provided a test case with a failing curl operation: when we POST
|
||||
to a site with --digest (or similar) set, and the server responded with a 302
|
||||
Location: to the "authprobe" request, it was not treated correctly. We still
|
||||
will behave badly if FOLLOWLOCATION is enabled for this case, but I'm not
|
||||
in the mood to dive into this right now and will leave it as-is for now.
|
||||
Verified my fix with test case 177.
|
||||
|
||||
Daniel (18 June 2004)
|
||||
- Gisle Vanem's patch that provides more details from the SSL layers (if you
|
||||
use an OpenSSL version that supports it). It also introduces two new types
|
||||
of data that can be sent to the debug callback: CURLINFO_SSL_DATA_IN and
|
||||
CURLINFO_SSL_DATA_OUT.
|
||||
|
||||
- With David Byron's test server I could repeat his problem and make sure that
|
||||
POSTing over HTTPS:// with NTLM works fine now. There was a general problem
|
||||
with multi-pass authentication with non-GET operations with CONNECT.
|
||||
|
||||
Daniel (16 June 2004)
|
||||
- Modified to keep the upload byte counter in an curl_off_t, not an int as
|
||||
before. 32bits is not enough. This is most likely the bug Jean-Louis Lemaire
|
||||
reported that makes 2GB FTP uploads to report error ("unaligned file sizes")
|
||||
when completed.
|
||||
|
||||
Daniel (15 June 2004)
|
||||
- Luca Alteas reported a problem that I fixed: if you did a POST with
|
||||
CURLAUTH_DIGEST set but the server didn't require any authentication,
|
||||
libcurl would repeatedly send HEAD lots of times until it gives up. This was
|
||||
actually the case for all multi-pass authentications. Added test case 174,
|
||||
175 and 176 to verify this.
|
||||
|
||||
Daniel (14 June 2004)
|
||||
- Multipart formposts uploading files no longer inserts the files themselves
|
||||
into the huge prebuilt chunk. This enables libcurl to formpost files that is
|
||||
larger than the amount of system memory. When the file given is passed on
|
||||
stdin, libcurl still uses the old method of reading the full fill before the
|
||||
upload takes place. This approach was selected in order to not alter the
|
||||
behavior for existing applications, as when using stdin libcurl can't know
|
||||
the size of the upload and chunked transfer-encoding can only be used on
|
||||
HTTP 1.1 servers.
|
||||
|
||||
Daniel (13 June 2004)
|
||||
- Gisle found out that we did wildcard cert name checks wrong, so that parts
|
||||
of the check wrongly was case sensitive.
|
||||
|
||||
Daniel (11 June 2004)
|
||||
- Tim Sneddon brought a minor VMS fix to make curl build properly on his VMS
|
||||
machine. He also had some interesting libcurl patches... they might be able
|
||||
to do in a slightly nicer way. Discussions are in progress.
|
||||
|
||||
Daniel (10 June 2004)
|
||||
- Gisle Vanem brought code cleanupsm better verbose output and better connect
|
||||
timeout handling when attempting to connect to a host that resolves to
|
||||
multiple IP addresses.
|
||||
|
||||
- Steven Bazyl and Seshubabu Pasam pointed out a bug on win32 when freeing the
|
||||
path after a file:// transfer.
|
||||
|
||||
Daniel (9 June 2004)
|
||||
- Alexander Krasnostavsky made 'configure --disable-http' work to build libcurl
|
||||
without HTTP support. I added a new return code for curl_formadd() in case
|
||||
libcurl is built with HTTP disable: CURL_FORMADD_DISABLED.
|
||||
|
||||
- Alexander Krasnostavsky pointed out a missing file in the generated
|
||||
curllib.dsp file, and now people building with this should get a libcurl.lib
|
||||
file generated as it used to do before we generated this file.
|
||||
|
||||
Daniel (8 June 2004)
|
||||
- Marty Kuhrt fixed a minor build problem for VMS.
|
||||
|
||||
Daniel (7 June 2004)
|
||||
- Reverted the configure check from the 4th since it obviously didn't work.
|
||||
Remade it in a different manner that hopefully works better.
|
||||
|
||||
Daniel (4 June 2004)
|
||||
- G<>nter Knauf brought patches to make curl build fine on NetWare again.
|
||||
|
||||
- Made the configure checks for strerror_r() not exit the configure script
|
||||
when built for cross-compiling.
|
||||
|
||||
Daniel (3 June 2004)
|
||||
- Chris Gaukroger pointed out that 'make test' attempts to run the tests even
|
||||
if curl is built cross-compiled. I've now made it output a short message
|
||||
instead, saying it isn't possible to do.
|
||||
|
||||
- Alexander Krasnostavsky brought FTP 3rd party transfer support to libcurl.
|
||||
You can now use libcurl to transfer files between two remote hosts using
|
||||
FTP. There are a bunch of new options to control this with:
|
||||
CURLOPT_SOURCE_HOST
|
||||
CURLOPT_SOURCE_USERPWD
|
||||
CURLOPT_SOURCE_PATH
|
||||
CURLOPT_SOURCE_PORT
|
||||
CURLOPT_PASV_HOST
|
||||
CURLOPT_SOURCE_PREQUOTE
|
||||
CURLOPT_SOURCE_POSTQUOTE
|
||||
|
||||
(They still remain to be documented properly in the curl_easy_setopt man
|
||||
page.)
|
||||
|
||||
When using this, the ordinary CURLOPT_URL specifies the target URL, and you
|
||||
specify the source data with these additional options. ftp3rdparty.c is a
|
||||
new example source code showing how to use this.
|
||||
|
||||
- Vincent Bronner fixed the HTTP Digest code to use the proxy user name and
|
||||
password when doing proxy authentication, it previously always used the host
|
||||
user name and password!
|
||||
|
||||
Daniel (2 June 2004)
|
||||
- CURLOPT_UPLOAD and CURLOPT_PUT now do the exact same thing internally, which
|
||||
fixes some old confusions on when which of these should be used and what the
|
||||
differences are.
|
||||
|
||||
- Applied Gisle's fixes to make curl build fine with lcc-win32
|
||||
|
||||
Version 7.12.0 (2 June 2004)
|
||||
|
||||
Daniel (1 June 2004)
|
||||
|
@@ -24,7 +24,7 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
EXTRA_DIST = CHANGES COPYING maketgz reconf Makefile.dist \
|
||||
curl-config.in curl-style.el sample.emacs testcurl.sh RELEASE-NOTES
|
||||
curl-config.in curl-style.el sample.emacs RELEASE-NOTES
|
||||
|
||||
bin_SCRIPTS = curl-config
|
||||
|
||||
|
@@ -41,6 +41,10 @@ mingw32-ssl:
|
||||
cd lib & make -f Makefile.m32 SSL=1 ZLIB=1
|
||||
cd src & make -f Makefile.m32 SSL=1 ZLIB=1
|
||||
|
||||
mingw32-clean:
|
||||
cd lib & make -f Makefile.m32 clean
|
||||
cd src & make -f Makefile.m32 clean
|
||||
|
||||
vc:
|
||||
cd lib
|
||||
nmake /f Makefile.vc6 cfg=release
|
||||
@@ -82,8 +86,16 @@ amiga:
|
||||
cd ./src && make -f makefile.amiga
|
||||
|
||||
netware:
|
||||
cd lib && make -f Makefile.netware
|
||||
cd src && make -f Makefile.netware
|
||||
$(MAKE) -C lib -f Makefile.netware
|
||||
$(MAKE) -C src -f Makefile.netware
|
||||
|
||||
netware-ssl:
|
||||
$(MAKE) -C lib -f Makefile.netware SSL=1
|
||||
$(MAKE) -C src -f Makefile.netware SSL=1
|
||||
|
||||
netware-clean:
|
||||
$(MAKE) -C lib -f Makefile.netware clean
|
||||
$(MAKE) -C src -f Makefile.netware clean
|
||||
|
||||
unix: all
|
||||
|
||||
|
@@ -1,62 +1,51 @@
|
||||
Curl and libcurl 7.12.0.
|
||||
Curl and libcurl 7.12.1
|
||||
|
||||
Public curl release number: 81
|
||||
Releases counted from the very beginning: 108
|
||||
Public curl release number: 82
|
||||
Releases counted from the very beginning: 109
|
||||
Available command line options: 96
|
||||
Available curl_easy_setopt() options: 113
|
||||
Available curl_easy_setopt() options: 120
|
||||
Number of public functions in libcurl: 36
|
||||
|
||||
A special thanks to:
|
||||
|
||||
archivas.com and Alan Pinstein, for paying me to focus on their requests
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o added ability to "upload" to file:// URLs
|
||||
o added curl_global_init_mem()
|
||||
o removed curl_formparse()
|
||||
o the MSVC project file in the release archive is automatically built
|
||||
o curl --proxy-digest is a new command line option
|
||||
o the Windows version of libcurl can use wldap32.dll for LDAP
|
||||
o added curl_easy_strerror(), curl_multi_strerror() and curl_share_strerror()
|
||||
o IPv6-enabled Windows hosts now resolves names threaded/asynch as well
|
||||
o configure --with-libidn can be used to point out the root dir of a libidn
|
||||
installation (version 0.4.5 or later) for curl to use, then libcurl can
|
||||
resolve and use IDNA names (domain names with "international" letters)
|
||||
o read callbacks can stop the transfer by returning CURL_READFUNC_ABORT
|
||||
o libcurl-tutorial.3 is the new man page formerly known as libcurl-the-guide
|
||||
o additional SSL trace data might be sent to the debug callback using two new
|
||||
types: CURLINFO_SSL_DATA_IN and CURLINFO_SSL_DATA_OUT
|
||||
o multipart formposts can upload files larger than system memory
|
||||
o the curl tool continues with the next URL even if one transfer fails
|
||||
o FTP 3rd party transfer support - seven new setopt() options
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o incoming cookies with domains set with a prefixed dot now works better
|
||||
o CURLOPT_COOKIEFILE and CURLOPT_COOKIE can be used in the same request
|
||||
o improved peer certificate name verification
|
||||
o allocation failures cause no leaks nor crashes
|
||||
o the progress meter display now handles file sizes up to full 8 exabytes
|
||||
(which is as high a signed 64 bit number can reach)
|
||||
o general HTTP authentication improvements
|
||||
o HTTP Digest authentication with the proxy works
|
||||
o mulipart formposting with -F and file names with spaces work again
|
||||
o curl_easy_duphandle() now works when ares-enabled
|
||||
o HTTP Digest authentication works a lot more like the RFC says
|
||||
o curl works with telnet and stdin properly on Windows
|
||||
o configure --without-ssl works even when pkg-config has OpenSSL details
|
||||
o src/hugehelp.c builds correct again in non-configure build environments
|
||||
o cookies can now hold 4999 bytes of content
|
||||
o HTTP POST/PUT with NTLM/Digest/Negotiate to a URL returning 3XX
|
||||
o HTTPS POST/PUT over a proxy requiring NTLM/Digest/Negotiate works now
|
||||
o less restrictive libidn requirements, 0.4.1 or later is fine
|
||||
o fixed HTTP POST or PUT with Digest/Negotiate/NTLM selected but the server
|
||||
didn't require any authentication
|
||||
o win32 file:// transfer free memory bug
|
||||
o configure --disable-http builds a libcurl without HTTP support
|
||||
o CURLOPT_FILETIME had wrong type, it expects a long argument
|
||||
o builds fine with Borland on Windows again
|
||||
o the msvc curllib.dsp now builds the libcurl.lib file again
|
||||
o builds fine on VMS again
|
||||
o builds fine on NetWare again
|
||||
o HTTP Digest authentication with proxies uses correct user name + password
|
||||
o now builds fine with lcc-win32
|
||||
|
||||
Other curl-related news since the previous public release:
|
||||
|
||||
o The CVS repository was moved to cool.haxx.se
|
||||
o AdacURL 7.11.2 was released: http://www.almroth.com/adacurl/
|
||||
o PycURL 7.11.3 was released: http://pycurl.sourceforge.net
|
||||
o A new German download mirror: http://www.mirrorspace.org/curl/
|
||||
o Two new mailing lists are available:
|
||||
curl-and-python - for python programmers using pycurl or curl
|
||||
curl-perl-commmits - receives commits done to the curl-perl CVS module
|
||||
o James Hu took over after Kevin Roth as maintainer of the curl package on
|
||||
cygwin. Many saludos to Kevin for a work well done during many years.
|
||||
o Gambas binding for libcurl: http://gambas.sf.net/
|
||||
o pycurl 7.12.0 was released http://pycurl.sf.net/
|
||||
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Gisle Vanem, Tommy Tam, Luca Altea, James Bursa, Mihai Ionescu, Michael
|
||||
Benedict, Andr<64>s Garc<72>a, Joe Halpin, Seshubabu Pasam, Peter Sylvester, Robert
|
||||
D. Young, Jesse Noller, David Byron, Massimiliano Ziccardi, Mohun Biswas,
|
||||
Renaud Duhaut
|
||||
Gisle Vanem, Vincent Bronner, Alexander Krasnostavsky, Chris Gaukroger,
|
||||
G<EFBFBD>nter Knauf, Marty Kuhrt, Kjetil Jacobsen, Steven Bazyl, Seshubabu Pasam,
|
||||
Luca Alteas, Jean-Louis Lemaire, David Byron, David Cohen
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
16
TODO-RELEASE
16
TODO-RELEASE
@@ -1,13 +1,17 @@
|
||||
Issues not sorted in any particular order.
|
||||
#[num] refers to bug report numbers.
|
||||
UNASSIGNED means that no person has publicly stated to work on the issue.
|
||||
DELETE means the issue is subject for dismissal
|
||||
|
||||
To get fixed in 7.12.0 (planned release: June 2004)
|
||||
======================
|
||||
|
||||
To get fixed in 7.12.1 (planned release: August 2004)
|
||||
======================
|
||||
|
||||
* FTP 3rd party transfers
|
||||
35 - Fix multi interface when connecting to host with multiple IP addresses:
|
||||
http://curl.haxx.se/mail/lib-2004-06/0163.html and
|
||||
http://curl.haxx.se/mail/lib-2004-06/0167.html
|
||||
UNASSIGNED
|
||||
|
||||
* Bugfixes reported until late July
|
||||
|
||||
To get fixed in 7.12.2 (planned release: December 2004)
|
||||
======================
|
||||
|
||||
Bugfixes reported until late November
|
||||
|
23
acinclude.m4
23
acinclude.m4
@@ -423,13 +423,18 @@ main () {
|
||||
return 0;
|
||||
}
|
||||
],
|
||||
GLIBC_STRERROR_R="1"
|
||||
AC_DEFINE(HAVE_GLIBC_STRERROR_R, 1, [we have a glibc-style strerror_r()])
|
||||
AC_MSG_RESULT([yes]),
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_RESULT([no]),
|
||||
dnl cross-compiling!
|
||||
AC_MSG_NOTICE([cannot determine strerror_r() style: edit lib/config.h manually!])
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([for a POSIX strerror_r API])
|
||||
AC_TRY_RUN([
|
||||
if test -z "$GLIBC_STRERROR_R"; then
|
||||
|
||||
AC_MSG_CHECKING([for a POSIX strerror_r API])
|
||||
AC_TRY_RUN([
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
int
|
||||
@@ -444,12 +449,16 @@ main () {
|
||||
return 0;
|
||||
}
|
||||
],
|
||||
AC_DEFINE(HAVE_POSIX_STRERROR_R, 1, [we have a POSIX-style strerror_r()])
|
||||
AC_MSG_RESULT([yes]),
|
||||
AC_MSG_RESULT([no])
|
||||
AC_DEFINE(HAVE_POSIX_STRERROR_R, 1, [we have a POSIX-style strerror_r()])
|
||||
AC_MSG_RESULT([yes]),
|
||||
AC_MSG_RESULT([no]) ,
|
||||
dnl cross-compiling!
|
||||
AC_MSG_NOTICE([cannot determine strerror_r() style: edit lib/config.h manually!])
|
||||
)
|
||||
|
||||
fi
|
||||
fi dnl if not using glibc API
|
||||
|
||||
fi dnl we have a strerror_r
|
||||
|
||||
])
|
||||
|
||||
|
21
ares/CHANGES
21
ares/CHANGES
@@ -1,5 +1,26 @@
|
||||
Changelog for the c-ares project
|
||||
|
||||
* June 10
|
||||
- Gisle Vanem's init patch for Windows:
|
||||
|
||||
The init_by_resolv_conf() function fetches the DNS-server(s)
|
||||
from a series of registry branches.
|
||||
|
||||
This can be wrong in the case where DHCP has assigned nameservers, but the
|
||||
user has overridden these servers with other prefered settings. Then it's
|
||||
wrong to use the DHCPNAMESERVER setting in registry.
|
||||
|
||||
In the case of no global DHCP-assigned or fixed servers, but DNS server(s)
|
||||
per adapter, one has to query the adapter branches. But how can c-ares know
|
||||
which adapter is valid for use? AFAICS it can't. There could be one adapter
|
||||
that is down (e.g. a VPN adapter).
|
||||
|
||||
So it's better to leave this to the IP Helper API (iphlapi) available in
|
||||
Win-98/2000 and later. My patch falls-back to the old way if not available.
|
||||
|
||||
* June 8
|
||||
- James Bursa fixed an init issue for RISC OS.
|
||||
|
||||
* May 11
|
||||
- Nico Stappenbelt reported that when processing domain and search lines in
|
||||
the resolv.conf file, the first entry encountered is processed and used as
|
||||
|
133
ares/ares_init.c
133
ares/ares_init.c
@@ -17,6 +17,8 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include "nameser.h"
|
||||
#include <iphlpapi.h>
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
@@ -231,24 +233,24 @@ static int init_by_environment(ares_channel channel)
|
||||
|
||||
return ARES_SUCCESS;
|
||||
}
|
||||
#ifdef WIN32
|
||||
static int get_res_size_nt(HKEY hKey, char *subkey, int *size)
|
||||
{
|
||||
return RegQueryValueEx(hKey, subkey, 0, NULL, NULL, size);
|
||||
}
|
||||
|
||||
/* Warning: returns a dynamically allocated buffer, the user MUST
|
||||
#ifdef WIN32
|
||||
/*
|
||||
* Warning: returns a dynamically allocated buffer, the user MUST
|
||||
* use free() if the function returns 1
|
||||
*/
|
||||
static int get_res_nt(HKEY hKey, char *subkey, char **obuf)
|
||||
static int get_res_nt(HKEY hKey, const char *subkey, char **obuf)
|
||||
{
|
||||
/* Test for the size we need */
|
||||
int size = 0;
|
||||
DWORD size = 0;
|
||||
int result;
|
||||
|
||||
result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
|
||||
if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
|
||||
return 0;
|
||||
*obuf = malloc(size+1);
|
||||
if (!*obuf)
|
||||
return 0;
|
||||
|
||||
if (RegQueryValueEx(hKey, subkey, 0, NULL, *obuf, &size) != ERROR_SUCCESS)
|
||||
{
|
||||
@@ -263,29 +265,99 @@ static int get_res_nt(HKEY hKey, char *subkey, char **obuf)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_res_interfaces_nt(HKEY hKey, char *subkey, char **obuf)
|
||||
static int get_res_interfaces_nt(HKEY hKey, const char *subkey, char **obuf)
|
||||
{
|
||||
char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */
|
||||
int enum_size = 39;
|
||||
DWORD enum_size = 39;
|
||||
int idx = 0;
|
||||
HKEY hVal;
|
||||
|
||||
while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0,
|
||||
NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
int rc;
|
||||
|
||||
enum_size = 39;
|
||||
if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) !=
|
||||
ERROR_SUCCESS)
|
||||
continue;
|
||||
if (!get_res_nt(hVal, subkey, obuf))
|
||||
RegCloseKey(hVal);
|
||||
else
|
||||
{
|
||||
rc = get_res_nt(hVal, subkey, obuf);
|
||||
RegCloseKey(hVal);
|
||||
if (rc)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_iphlpapi_dns_info (char *ret_buf, size_t ret_size)
|
||||
{
|
||||
FIXED_INFO *fi = alloca (sizeof(*fi));
|
||||
DWORD size = sizeof (*fi);
|
||||
DWORD WINAPI (*GetNetworkParams) (FIXED_INFO*, DWORD*); /* available only on Win-98/2000+ */
|
||||
HMODULE handle;
|
||||
IP_ADDR_STRING *ipAddr;
|
||||
int i, count = 0;
|
||||
int debug = 0;
|
||||
size_t ip_size = sizeof("255.255.255.255,")-1;
|
||||
size_t left = ret_size;
|
||||
char *ret = ret_buf;
|
||||
|
||||
if (!fi)
|
||||
return (0);
|
||||
|
||||
handle = LoadLibrary ("iphlpapi.dll");
|
||||
if (!handle)
|
||||
return (0);
|
||||
|
||||
(void*)GetNetworkParams = GetProcAddress (handle, "GetNetworkParams");
|
||||
if (!GetNetworkParams)
|
||||
goto quit;
|
||||
|
||||
if ((*GetNetworkParams) (fi, &size) != ERROR_BUFFER_OVERFLOW)
|
||||
goto quit;
|
||||
|
||||
fi = alloca (size);
|
||||
if (!fi || (*GetNetworkParams) (fi, &size) != ERROR_SUCCESS)
|
||||
goto quit;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
printf ("Host Name: %s\n", fi->HostName);
|
||||
printf ("Domain Name: %s\n", fi->DomainName);
|
||||
printf ("DNS Servers:\n"
|
||||
" %s (primary)\n", fi->DnsServerList.IpAddress.String);
|
||||
}
|
||||
if (inet_addr(fi->DnsServerList.IpAddress.String) != INADDR_NONE &&
|
||||
left > ip_size)
|
||||
{
|
||||
ret += sprintf (ret, "%s,", fi->DnsServerList.IpAddress.String);
|
||||
left -= ret - ret_buf;
|
||||
count++;
|
||||
}
|
||||
|
||||
for (i = 0, ipAddr = fi->DnsServerList.Next; ipAddr && left > ip_size;
|
||||
ipAddr = ipAddr->Next, i++)
|
||||
{
|
||||
if (inet_addr(ipAddr->IpAddress.String) != INADDR_NONE)
|
||||
{
|
||||
ret += sprintf (ret, "%s,", ipAddr->IpAddress.String);
|
||||
left -= ret - ret_buf;
|
||||
count++;
|
||||
}
|
||||
if (debug)
|
||||
printf (" %s (secondary %d)\n", ipAddr->IpAddress.String, i+1);
|
||||
}
|
||||
|
||||
quit:
|
||||
if (handle)
|
||||
FreeLibrary (handle);
|
||||
|
||||
if (debug && left <= ip_size)
|
||||
printf ("Too many nameservers. Truncating to %d addressess", count);
|
||||
if (ret > ret_buf)
|
||||
ret[-1] = '\0';
|
||||
return (count);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int init_by_resolv_conf(ares_channel channel)
|
||||
@@ -298,6 +370,11 @@ static int init_by_resolv_conf(ares_channel channel)
|
||||
#ifdef WIN32
|
||||
|
||||
/*
|
||||
NameServer info via IPHLPAPI (IP helper API):
|
||||
GetNetworkParams() should be the trusted source for this.
|
||||
Available in Win-98/2000 and later. If that fail, fall-back to
|
||||
registry information.
|
||||
|
||||
NameServer Registry:
|
||||
|
||||
On Windows 9X, the DNS server can be found in:
|
||||
@@ -320,9 +397,17 @@ DhcpNameServer
|
||||
DWORD data_type;
|
||||
DWORD bytes;
|
||||
DWORD result;
|
||||
DWORD keysize = MAX_PATH;
|
||||
char buf[256];
|
||||
|
||||
status = ARES_EFILE;
|
||||
if (channel->nservers > -1) /* don't override ARES_OPT_SERVER */
|
||||
return ARES_SUCCESS;
|
||||
|
||||
if (get_iphlpapi_dns_info(buf,sizeof(buf)) > 0)
|
||||
{
|
||||
status = config_nameserver(&servers, &nservers, buf);
|
||||
if (status == ARES_SUCCESS)
|
||||
goto okay;
|
||||
}
|
||||
|
||||
if (IsNT)
|
||||
{
|
||||
@@ -388,15 +473,8 @@ DhcpNameServer
|
||||
RegCloseKey(mykey);
|
||||
}
|
||||
|
||||
if (status != ARES_EFILE)
|
||||
{
|
||||
/*
|
||||
if (!channel->lookups) {
|
||||
status = config_lookup(channel, "file bind");
|
||||
}
|
||||
*/
|
||||
if (status == ARES_SUCCESS)
|
||||
status = ARES_EOF;
|
||||
}
|
||||
|
||||
#elif defined(riscos)
|
||||
|
||||
@@ -404,7 +482,7 @@ DhcpNameServer
|
||||
system variable Inet$Resolvers, space separated. */
|
||||
|
||||
line = getenv("Inet$Resolvers");
|
||||
status = ARES_EFILE;
|
||||
status = ARES_EOF;
|
||||
if (line) {
|
||||
char *resolvers = strdup(line), *pos, *space;
|
||||
|
||||
@@ -474,6 +552,9 @@ DhcpNameServer
|
||||
}
|
||||
|
||||
/* If we got any name server entries, fill them in. */
|
||||
#ifdef WIN32
|
||||
okay:
|
||||
#endif
|
||||
if (servers)
|
||||
{
|
||||
channel->servers = servers;
|
||||
|
@@ -1365,6 +1365,8 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(CROSSCOMPILING, test x$cross_compiling = xyes)
|
||||
|
||||
AC_CONFIG_FILES([Makefile \
|
||||
docs/Makefile \
|
||||
docs/examples/Makefile \
|
||||
|
@@ -126,3 +126,5 @@ visitors to the curl.haxx.se site. Five official web mirrors.
|
||||
December 2003, full-fledged SSL for FTP is supported.
|
||||
|
||||
January 2004: curl 7.11.0 introduced large file support.
|
||||
|
||||
June 2004: curl 7.12.0 introduced IDN support. 10 official web mirrors.
|
||||
|
20
docs/MANUAL
20
docs/MANUAL
@@ -851,7 +851,7 @@ MAILING LISTS
|
||||
|
||||
For your convenience, we have several open mailing lists to discuss curl,
|
||||
its development and things relevant to this. Get all info at
|
||||
http://curl.haxx.se/mail/. The lists available are:
|
||||
http://curl.haxx.se/mail/. Some of the lists available are:
|
||||
|
||||
curl-users
|
||||
|
||||
@@ -865,24 +865,18 @@ MAILING LISTS
|
||||
|
||||
curl-announce
|
||||
|
||||
Low-traffic. Only announcements of new public versions.
|
||||
Low-traffic. Only receives announcements of new public versions. At worst,
|
||||
that makes something like one or two mails per month, but usually only one
|
||||
mail every second month.
|
||||
|
||||
curl-and-PHP
|
||||
curl-and-php
|
||||
|
||||
Using the curl functions in PHP. Everything curl with a PHP angle. Or PHP
|
||||
with a curl angle.
|
||||
|
||||
curl-commits
|
||||
curl-and-python
|
||||
|
||||
Receives notifications on all CVS commits done to the curl source module.
|
||||
This can become quite a large amount of mails during intense development,
|
||||
be aware. This is for us who like email...
|
||||
|
||||
curl-www-commits
|
||||
|
||||
Receives notifications on all CVS commits done to the curl www module
|
||||
(basicly the web site). This can become quite a large amount of mails
|
||||
during intense changing, be aware. This is for us who like email...
|
||||
Python hackers using curl with or without the python binding pycurl.
|
||||
|
||||
Please direct curl questions, feature requests and trouble reports to one of
|
||||
these mailing lists instead of mailing any individual.
|
||||
|
@@ -17,7 +17,7 @@ CLEANFILES = $(GENHTMLPAGES) $(PDFPAGES)
|
||||
EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
|
||||
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \
|
||||
KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
|
||||
libcurl-the-guide $(PDFPAGES) LICENSE-MIXING
|
||||
$(PDFPAGES) LICENSE-MIXING
|
||||
|
||||
MAN2HTML= roffit < $< >$@
|
||||
|
||||
|
@@ -9,7 +9,7 @@ EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.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 simplepost.c makefile.dj curlx.c https.c \
|
||||
multi-debugcallback.c fileupload.c
|
||||
multi-debugcallback.c fileupload.c getinfo.c ftp3rdparty.c
|
||||
|
||||
all:
|
||||
@echo "done"
|
||||
|
104
docs/examples/ftp3rdparty.c
Normal file
104
docs/examples/ftp3rdparty.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/types.h>
|
||||
#include <curl/easy.h>
|
||||
|
||||
/*
|
||||
* This is an example showing how to transfer a file between two remote hosts.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
char sourceFileName[] = "/tmp/file";
|
||||
char targetFileName[] = "/tmp/curlTargetTest.dat";
|
||||
char sourceHost[] = "source";
|
||||
char targetHost[] = "target";
|
||||
char sourceUserPass[] = "user:pass";
|
||||
char targetUserPass[] = "user:pass";
|
||||
char url[100];
|
||||
|
||||
struct curl_slist *source_pre_cmd = NULL;
|
||||
struct curl_slist *target_pre_cmd = NULL;
|
||||
struct curl_slist *source_post_cmd = NULL;
|
||||
struct curl_slist *target_post_cmd = NULL;
|
||||
char cmd[] = "PWD"; /* just to test */
|
||||
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (curl) {
|
||||
sprintf(url, "ftp://%s@%s/%s", targetUserPass, targetHost, targetFileName);
|
||||
printf("%s\n", url);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
|
||||
/* Set a proxy host */
|
||||
curl_easy_setopt(curl, CURLOPT_SOURCE_HOST, sourceHost);
|
||||
|
||||
/* Set a proxy user and password */
|
||||
curl_easy_setopt(curl, CURLOPT_SOURCE_USERPWD, sourceUserPass);
|
||||
|
||||
/* Set a proxy full file name */
|
||||
curl_easy_setopt(curl, CURLOPT_SOURCE_PATH, sourceFileName);
|
||||
|
||||
/* Set a proxy passive host */
|
||||
curl_easy_setopt(curl, CURLOPT_PASV_HOST, 0); /* optional */
|
||||
|
||||
/* build a list of commands to pass to libcurl */
|
||||
source_pre_cmd = curl_slist_append(source_pre_cmd, cmd);
|
||||
/* Set a proxy pre-quote command */
|
||||
curl_easy_setopt(curl, CURLOPT_SOURCE_PREQUOTE, source_pre_cmd);
|
||||
|
||||
/* build a list of commands to pass to libcurl */
|
||||
target_pre_cmd = curl_slist_append(target_pre_cmd, cmd);
|
||||
/* Set a pre-quote command */
|
||||
curl_easy_setopt(curl, CURLOPT_PREQUOTE, target_pre_cmd);
|
||||
|
||||
/* build a list of commands to pass to libcurl */
|
||||
source_post_cmd = curl_slist_append(source_post_cmd, cmd);
|
||||
/* Set a proxy post-quote command */
|
||||
curl_easy_setopt(curl, CURLOPT_SOURCE_POSTQUOTE, source_post_cmd);
|
||||
|
||||
/* build a list of commands to pass to libcurl */
|
||||
target_post_cmd = curl_slist_append(target_post_cmd, cmd);
|
||||
/* Set a post-quote command */
|
||||
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, target_post_cmd);
|
||||
|
||||
/* Switch on full protocol/debug output */
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
/* clean up the FTP commands list */
|
||||
curl_slist_free_all(source_pre_cmd);
|
||||
curl_slist_free_all(target_pre_cmd);
|
||||
curl_slist_free_all(source_post_cmd);
|
||||
curl_slist_free_all(target_post_cmd);
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if(CURLE_OK != res) {
|
||||
/* we failed */
|
||||
fprintf(stderr, "curl told us %d\n", res);
|
||||
}
|
||||
}
|
||||
|
||||
curl_global_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
37
docs/examples/getinfo.c
Normal file
37
docs/examples/getinfo.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(CURLE_OK == res) {
|
||||
char *ct;
|
||||
/* ask for the content-type */
|
||||
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
|
||||
|
||||
if((CURLE_OK == res) && ct)
|
||||
printf("We received Content-Type: %s\n", ct);
|
||||
}
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -16,7 +16,7 @@ About this Document
|
||||
|
||||
This document will refer to 'the user' as the person writing the source code
|
||||
that uses libcurl. That would probably be you or someone in your position.
|
||||
What will be generally refered to as 'the program' will be the collected
|
||||
What will be generally referred to as 'the program' will be the collected
|
||||
source code that you write that is using libcurl for transfers. The program
|
||||
is outside libcurl and libcurl is outside of the program.
|
||||
|
||||
@@ -44,7 +44,7 @@ Building
|
||||
When having compiled the program, you need to link your object files to
|
||||
create a single executable. For that to succeed, you need to link with
|
||||
libcurl and possibly also with other libraries that libcurl itself depends
|
||||
on. Like OpenSSL librararies, but even some standard OS libraries may be
|
||||
on. Like OpenSSL libraries, but even some standard OS libraries may be
|
||||
needed on the command line. To figure out which flags to use, once again
|
||||
the 'curl-config' tool comes to the rescue:
|
||||
|
||||
@@ -65,6 +65,8 @@ Building
|
||||
possibly together with a few other features that can be on and off on
|
||||
different libcurls.
|
||||
|
||||
See also the "Features libcurl Provides" further down.
|
||||
|
||||
|
||||
Portable Code in a Portable World
|
||||
|
||||
@@ -86,22 +88,22 @@ Global Preparation
|
||||
curl_global_init()
|
||||
|
||||
and it takes one parameter which is a bit pattern that tells libcurl what to
|
||||
intialize. Using CURL_GLOBAL_ALL will make it initialize all known internal
|
||||
initialize. Using CURL_GLOBAL_ALL will make it initialize all known internal
|
||||
sub modules, and might be a good default option. The current two bits that
|
||||
are specified are:
|
||||
|
||||
CURL_GLOBAL_WIN32 which only does anything on Windows machines. When used on
|
||||
a Windows machine, it'll make libcurl intialize the win32 socket
|
||||
a Windows machine, it'll make libcurl initialize the win32 socket
|
||||
stuff. Without having that initialized properly, your program cannot use
|
||||
sockets properly. You should only do this once for each application, so if
|
||||
your program already does this or of another library in use does it, you
|
||||
should not tell libcurl to do this as well.
|
||||
|
||||
CURL_GLOBAL_SSL which only does anything on libcurls compiled and built
|
||||
SSL-enabled. On these systems, this will make libcurl init OpenSSL properly
|
||||
for this application. This is only needed to do once for each application so
|
||||
if your program or another library already does this, this bit should not be
|
||||
needed.
|
||||
SSL-enabled. On these systems, this will make libcurl initialize OpenSSL
|
||||
properly for this application. This is only needed to do once for each
|
||||
application so if your program or another library already does this, this
|
||||
bit should not be needed.
|
||||
|
||||
libcurl has a default protection mechanism that detects if curl_global_init()
|
||||
hasn't been called by the time curl_easy_perform() is called and if that is
|
||||
@@ -117,18 +119,26 @@ Global Preparation
|
||||
avoided. They should only be called once each.
|
||||
|
||||
|
||||
Features libcurl Provides
|
||||
|
||||
It is considered best-practice to determine libcurl features run-time rather
|
||||
than build-time (if possible of course). By calling curl_version_info() and
|
||||
checking tout he details of the returned struct, your program can figure out
|
||||
exactly what the currently running libcurl supports.
|
||||
|
||||
|
||||
Handle the Easy libcurl
|
||||
|
||||
libcurl version 7 is oriented around the so called easy interface. All
|
||||
operations in the easy interface are prefixed with 'curl_easy'.
|
||||
libcurl first introduced the so called easy interface. All operations in the
|
||||
easy interface are prefixed with 'curl_easy'.
|
||||
|
||||
Future libcurls will also offer the multi interface. More about that
|
||||
interface, what it is targeted for and how to use it is still only debated on
|
||||
the libcurl mailing list and developer web pages. Join up to discuss and
|
||||
figure out!
|
||||
Recent libcurl versions also offer the multi interface. More about that
|
||||
interface, what it is targeted for and how to use it is detailed in a
|
||||
separate chapter further down. You still need to understand the easy
|
||||
interface first, so please continue reading for better understanding.
|
||||
|
||||
To use the easy interface, you must first create yourself an easy handle. You
|
||||
need one handle for each easy session you want to perform. Basicly, you
|
||||
need one handle for each easy session you want to perform. Basically, you
|
||||
should use one handle for every thread you plan to use for transferring. You
|
||||
must never share the same handle in multiple threads.
|
||||
|
||||
@@ -145,7 +155,7 @@ Handle the Easy libcurl
|
||||
set in the handle until set again to something different. Alas, multiple
|
||||
requests using the same handle will use the same options.
|
||||
|
||||
Many of the informationals you set in libcurl are "strings", pointers to data
|
||||
Many of the options you set in libcurl are "strings", pointers to data
|
||||
terminated with a zero byte. Keep in mind that when you set strings with
|
||||
curl_easy_setopt(), libcurl will not copy the data. It will merely point to
|
||||
the data. You MUST make sure that the data remains available for libcurl to
|
||||
@@ -157,7 +167,7 @@ Handle the Easy libcurl
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://curl.haxx.se/");
|
||||
|
||||
Let's assume for a while that you want to receive data as the URL indentifies
|
||||
Let's assume for a while that you want to receive data as the URL identifies
|
||||
a remote resource you want to get here. Since you write a sort of application
|
||||
that needs this transfer, I assume that you would like to get the data passed
|
||||
to you directly instead of simply getting it passed to stdout. So, you write
|
||||
@@ -219,26 +229,21 @@ Handle the Easy libcurl
|
||||
Multi-threading issues
|
||||
|
||||
libcurl is completely thread safe, except for two issues: signals and alarm
|
||||
handlers. Signals are needed for a SIGPIPE handler, and the alarm() syscall
|
||||
is used to catch timeouts (mostly during DNS lookup).
|
||||
handlers. Signals are needed for a SIGPIPE handler, and the alarm() Bacall
|
||||
is used to catch timeouts (mostly during ENS lookup).
|
||||
|
||||
If you are accessing HTTPS or FTPS URLs in a multi-threaded manner, you are
|
||||
then of course using OpenSSL multi-threaded and it has itself a few
|
||||
requirements on this. Basicly, you need to provide one or two functions to
|
||||
requirements on this. Basilio, you need to provide one or two functions to
|
||||
allow it to function properly. For all details, see this:
|
||||
|
||||
http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
|
||||
|
||||
When using multiple threads you should first ignore SIGPIPE in your main
|
||||
thread and set the CURLOPT_NOSIGNAL option to TRUE for all handles.
|
||||
|
||||
Everything will work fine except that timeouts are not honored during the DNS
|
||||
lookup - which you can work around by building libcurl with ares-support.
|
||||
Ares is a library that provides asynchronous name resolves. Unfortunately,
|
||||
ares does not yet support IPv6.
|
||||
|
||||
For SIGPIPE info see the UNIX Socket FAQ at
|
||||
http://www.unixguide.net/network/socketfaq/2.22.shtml
|
||||
When using multiple threads you should set the CURLOPT_NOSIGNAL option to
|
||||
TRUE for all handles. Everything will work fine except that timeouts are not
|
||||
honored during the DNS lookup - which you can work around by building libcurl
|
||||
with c-ares support. c-ares is a library that provides asynchronous name
|
||||
resolves. Unfortunately, c-ares does not yet support IPv6.
|
||||
|
||||
Also, note that CURLOPT_DNS_USE_GLOBAL_CACHE is not thread-safe.
|
||||
|
||||
@@ -251,10 +256,10 @@ When It Doesn't Work
|
||||
|
||||
There's one golden rule when these things occur: set the CURLOPT_VERBOSE
|
||||
option to TRUE. It'll cause the library to spew out the entire protocol
|
||||
details it sends, some internal info and some received protcol data as well
|
||||
details it sends, some internal info and some received protocol data as well
|
||||
(especially when using FTP). If you're using HTTP, adding the headers in the
|
||||
received output to study is also a clever way to get a better understanding
|
||||
wht the server behaves the way it does. Include headers in the normal body
|
||||
why the server behaves the way it does. Include headers in the normal body
|
||||
output with CURLOPT_HEADER set TRUE.
|
||||
|
||||
Of course there are bugs left. We need to get to know about them to be able
|
||||
@@ -342,7 +347,7 @@ Passwords
|
||||
curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "myname:thesecret");
|
||||
|
||||
Another case where name and password might be needed at times, is for those
|
||||
users who need to athenticate themselves to a proxy they use. libcurl offers
|
||||
users who need to authenticate themselves to a proxy they use. libcurl offers
|
||||
another option for this, the CURLOPT_PROXYUSERPWD. It is used quite similar
|
||||
to the CURLOPT_USERPWD option like this:
|
||||
|
||||
@@ -382,7 +387,7 @@ HTTP Authentication
|
||||
many different ways a client can provide those credentials to the server and
|
||||
you can control what way libcurl will (attempt to) use. The default HTTP
|
||||
authentication method is called 'Basic', which is sending the name and
|
||||
password in clear-text in the HTTP request, base64-encoded. This is unsecure.
|
||||
password in clear-text in the HTTP request, base64-encoded. This is insecure.
|
||||
|
||||
At the time of this writing libcurl can be built to use: Basic, Digest, NTLM,
|
||||
Negotiate, GSS-Negotiate and SPNEGO. You can tell libcurl which one to use
|
||||
@@ -427,7 +432,7 @@ HTTP POSTing
|
||||
curl_easy_perform(easyhandle); /* post away! */
|
||||
|
||||
Simple enough, huh? Since you set the POST options with the
|
||||
CURLOPT_POSTFIELDS, this automaticly switches the handle to use POST in the
|
||||
CURLOPT_POSTFIELDS, this automatically switches the handle to use POST in the
|
||||
upcoming request.
|
||||
|
||||
Ok, so what if you want to post binary data that also requires you to set the
|
||||
@@ -454,12 +459,12 @@ HTTP POSTing
|
||||
curl_slist_free_all(headers); /* free the header list */
|
||||
|
||||
While the simple examples above cover the majority of all cases where HTTP
|
||||
POST operations are required, they don't do multipart formposts. Multipart
|
||||
POST operations are required, they don't do multi-part formposts. Multi-part
|
||||
formposts were introduced as a better way to post (possibly large) binary
|
||||
data and was first documented in the RFC1867. They're called multipart
|
||||
data and was first documented in the RFC1867. They're called multi-part
|
||||
because they're built by a chain of parts, each being a single unit. Each
|
||||
part has its own name and contents. You can in fact create and post a
|
||||
multipart formpost with the regular libcurl POST support described above, but
|
||||
multi-part formpost with the regular libcurl POST support described above, but
|
||||
that would require that you build a formpost yourself and provide to
|
||||
libcurl. To make that easier, libcurl provides curl_formadd(). Using this
|
||||
function, you add parts to the form. When you're done adding parts, you post
|
||||
@@ -553,7 +558,7 @@ Showing Progress
|
||||
|
||||
libcurl with C++
|
||||
|
||||
There's basicly only one thing to keep in mind when using C++ instead of C
|
||||
There's basically only one thing to keep in mind when using C++ instead of C
|
||||
when interfacing libcurl:
|
||||
|
||||
"The Callbacks Must Be Plain C"
|
||||
@@ -580,8 +585,8 @@ Proxies
|
||||
as a substitute for another".
|
||||
|
||||
Proxies are exceedingly common these days. Companies often only offer
|
||||
internet access to employees through their HTTP proxies. Network clients or
|
||||
user-agents ask the proxy for docuements, the proxy does the actual request
|
||||
Internet access to employees through their HTTP proxies. Network clients or
|
||||
user-agents ask the proxy for documents, the proxy does the actual request
|
||||
and then it returns them.
|
||||
|
||||
libcurl has full support for HTTP proxies, so when a given URL is wanted,
|
||||
@@ -591,7 +596,7 @@ Proxies
|
||||
The fact that the proxy is a HTTP proxy puts certain restrictions on what can
|
||||
actually happen. A requested URL that might not be a HTTP URL will be still
|
||||
be passed to the HTTP proxy to deliver back to libcurl. This happens
|
||||
transparantly, and an application may not need to know. I say "may", because
|
||||
transparently, and an application may not need to know. I say "may", because
|
||||
at times it is very important to understand that all operations over a HTTP
|
||||
proxy is using the HTTP protocol. For example, you can't invoke your own
|
||||
custom FTP commands or even proper FTP directory listings.
|
||||
@@ -612,9 +617,9 @@ Proxies
|
||||
|
||||
Environment Variables
|
||||
|
||||
libcurl automaticly checks and uses a set of environment variables to know
|
||||
what proxies to use for certain protocols. The names of the variables are
|
||||
following an ancient de facto standard and are built up as
|
||||
libcurl automatically checks and uses a set of environment variables to
|
||||
know what proxies to use for certain protocols. The names of the variables
|
||||
are following an ancient de facto standard and are built up as
|
||||
"[protocol]_proxy" (note the lower casing). Which makes the variable
|
||||
'http_proxy' checked for a name of a proxy to use when the input URL is
|
||||
HTTP. Following the same rule, the variable named 'ftp_proxy' is checked
|
||||
@@ -622,11 +627,12 @@ Proxies
|
||||
names of the variables simply allows different HTTP proxies to be used.
|
||||
|
||||
The proxy environment variable contents should be in the format
|
||||
"[protocol://]machine[:port]". Where the protocol:// part is simply
|
||||
ignored if present (so http://proxy and bluerk://proxy will do the same)
|
||||
and the optional port number specifies on which port the proxy operates on
|
||||
the host. If not specified, the internal default port number will be used
|
||||
and that is most likely *not* the one you would like it to be.
|
||||
"[protocol://][user:password]machine[:port]". Where the protocol:// part
|
||||
is simply ignored if present (so http://proxy and bluerk://proxy will do
|
||||
the same) and the optional port number specifies on which port the proxy
|
||||
operates on the host. If not specified, the internal default port number
|
||||
will be used and that is most likely *not* the one you would like it to
|
||||
be.
|
||||
|
||||
There are two special environment variables. 'all_proxy' is what sets
|
||||
proxy for any URL in case the protocol specific variable wasn't set, and
|
||||
@@ -637,7 +643,7 @@ Proxies
|
||||
SSL and Proxies
|
||||
|
||||
SSL is for secure point-to-point connections. This involves strong
|
||||
encryption and similar things, which effectivly makes it impossible for a
|
||||
encryption and similar things, which effectively makes it impossible for a
|
||||
proxy to operate as a "man in between" which the proxy's task is, as
|
||||
previously discussed. Instead, the only way to have SSL work over a HTTP
|
||||
proxy is to ask the proxy to tunnel trough everything without being able
|
||||
@@ -668,7 +674,7 @@ Proxies
|
||||
operations over a HTTP proxy. You can in fact use things such as FTP
|
||||
upload or FTP custom commands this way.
|
||||
|
||||
Again, this is often prevented by the adminstrators of proxies and is
|
||||
Again, this is often prevented by the administrators of proxies and is
|
||||
rarely allowed.
|
||||
|
||||
Tell libcurl to use proxy tunneling like this:
|
||||
@@ -682,13 +688,13 @@ Proxies
|
||||
|
||||
Proxy Auto-Config
|
||||
|
||||
Netscape first came up with this. It is basicly a web page (usually using
|
||||
a .pac extension) with a javascript that when executed by the browser with
|
||||
the requested URL as input, returns information to the browser on how to
|
||||
connect to the URL. The returned information might be "DIRECT" (which
|
||||
means no proxy should be used), "PROXY host:port" (to tell the browser
|
||||
where the proxy for this particular URL is) or "SOCKS host:port" (to
|
||||
direct the brower to a SOCKS proxy).
|
||||
Netscape first came up with this. It is basically a web page (usually
|
||||
using a .pac extension) with a javascript that when executed by the
|
||||
browser with the requested URL as input, returns information to the
|
||||
browser on how to connect to the URL. The returned information might be
|
||||
"DIRECT" (which means no proxy should be used), "PROXY host:port" (to tell
|
||||
the browser where the proxy for this particular URL is) or "SOCKS
|
||||
host:port" (to direct the browser to a SOCKS proxy).
|
||||
|
||||
libcurl has no means to interpret or evaluate javascript and thus it
|
||||
doesn't support this. If you get yourself in a position where you face
|
||||
@@ -706,7 +712,7 @@ Proxies
|
||||
- Ask your admins to stop this, for a static proxy setup or similar.
|
||||
|
||||
|
||||
Persistancy Is The Way to Happiness
|
||||
Persistence Is The Way to Happiness
|
||||
|
||||
Re-cycling the same easy handle several times when doing multiple requests is
|
||||
the way to go.
|
||||
@@ -717,11 +723,11 @@ Persistancy Is The Way to Happiness
|
||||
reduces network impact a lot.
|
||||
|
||||
Even if the connection is dropped, all connections involving SSL to the same
|
||||
host again, will benefit from libcurl's session ID cache that drasticly
|
||||
host again, will benefit from libcurl's session ID cache that drastically
|
||||
reduces re-connection time.
|
||||
|
||||
FTP connections that are kept alive saves a lot of time, as the command-
|
||||
response roundtrips are skipped, and also you don't risk getting blocked
|
||||
response round-trips are skipped, and also you don't risk getting blocked
|
||||
without permission to login again like on many FTP servers only allowing N
|
||||
persons to be logged in at the same time.
|
||||
|
||||
@@ -747,13 +753,13 @@ Persistancy Is The Way to Happiness
|
||||
used for the longest time. This is the default behavior.
|
||||
|
||||
CURLCLOSEPOLICY_OLDEST closes the oldest connection, the one that was
|
||||
createst the longest time ago.
|
||||
created the longest time ago.
|
||||
|
||||
There are, or at least were, plans to support a close policy that would call
|
||||
a user-specified callback to let the user be able to decide which connection
|
||||
to dump when this is necessary and therefor is the CURLOPT_CLOSEFUNCTION an
|
||||
existing option still today. Nothing ever uses this though and this will not
|
||||
be used within the forseeable future either.
|
||||
be used within the foreseeable future either.
|
||||
|
||||
To force your upcoming request to not use an already existing connection (it
|
||||
will even close one first if there happens to be one alive to the same host
|
||||
@@ -765,8 +771,8 @@ Persistancy Is The Way to Happiness
|
||||
|
||||
HTTP Headers Used by libcurl
|
||||
|
||||
When you use libcurl to do HTTP requeests, it'll pass along a series of
|
||||
headers automaticly. It might be good for you to know and understand these
|
||||
When you use libcurl to do HTTP requests, it'll pass along a series of
|
||||
headers automatically. It might be good for you to know and understand these
|
||||
ones.
|
||||
|
||||
Host
|
||||
@@ -777,7 +783,7 @@ HTTP Headers Used by libcurl
|
||||
|
||||
Pragma
|
||||
|
||||
"no-cache". Tells a possible proxy to not grap a copy from the cache but
|
||||
"no-cache". Tells a possible proxy to not grab a copy from the cache but
|
||||
to fetch a fresh one.
|
||||
|
||||
Accept:
|
||||
@@ -851,7 +857,7 @@ Customizing Operations
|
||||
|
||||
headers = curl_slist_append(headers, "Accept:");
|
||||
|
||||
Both replacing and cancelling internal headers should be done with careful
|
||||
Both replacing and canceling internal headers should be done with careful
|
||||
consideration and you should be aware that you may violate the HTTP
|
||||
protocol when doing so.
|
||||
|
||||
@@ -861,7 +867,7 @@ Customizing Operations
|
||||
chunked" when doing a non-GET HTTP operation, libcurl will switch over to
|
||||
"chunked" upload, even though the size of the data to upload might be
|
||||
known. By default, libcurl usually switches over to chunked upload
|
||||
automaticly if the upload data size is unknown.
|
||||
automatically if the upload data size is unknown.
|
||||
|
||||
HTTP Version
|
||||
|
||||
@@ -881,10 +887,10 @@ Customizing Operations
|
||||
you want to make for example your FTP transfers to behave differently.
|
||||
|
||||
Sending custom commands to a FTP server means that you need to send the
|
||||
comands exactly as the FTP server expects them (RFC959 is a good guide
|
||||
commands exactly as the FTP server expects them (RFC959 is a good guide
|
||||
here), and you can only use commands that work on the control-connection
|
||||
alone. All kinds of commands that requires data interchange and thus needs
|
||||
a data-connection must be left to libcurl's own judgement. Also be aware
|
||||
a data-connection must be left to libcurl's own judgment. Also be aware
|
||||
that libcurl will do its very best to change directory to the target
|
||||
directory before doing any transfer, so if you change directory (with CWD
|
||||
or similar) you might confuse libcurl and then it might not attempt to
|
||||
@@ -948,16 +954,16 @@ Cookies Without Chocolate Chips
|
||||
|
||||
curl_easy_setopt(easyhandle, CURLOPT_COOKIE, "name1=var1; name2=var2;");
|
||||
|
||||
In many cases, that is not enough. You might want to dynamicly save whatever
|
||||
cookies the remote server passes to you, and make sure those cookies are then
|
||||
use accordingly on later requests.
|
||||
In many cases, that is not enough. You might want to dynamically save
|
||||
whatever cookies the remote server passes to you, and make sure those cookies
|
||||
are then use accordingly on later requests.
|
||||
|
||||
One way to do this, is to save all headers you receive in a plain file and
|
||||
when you make a request, you tell libcurl to read the previous headers to
|
||||
figure out which cookies to use. Set header file to read cookies from with
|
||||
CURLOPT_COOKIEFILE.
|
||||
|
||||
The CURLOPT_COOKIEFILE option also automaticly enables the cookie parser in
|
||||
The CURLOPT_COOKIEFILE option also automatically enables the cookie parser in
|
||||
libcurl. Until the cookie parser is enabled, libcurl will not parse or
|
||||
understand incoming cookies and they will just be ignored. However, when the
|
||||
parser is enabled the cookies will be understood and the cookies will be kept
|
||||
@@ -970,7 +976,7 @@ Cookies Without Chocolate Chips
|
||||
If you rather use existing cookies that you've previously received with your
|
||||
Netscape or Mozilla browsers, you can make libcurl use that cookie file as
|
||||
input. The CURLOPT_COOKIEFILE is used for that too, as libcurl will
|
||||
automaticly find out what kind of file it is and act accordingly.
|
||||
automatically find out what kind of file it is and act accordingly.
|
||||
|
||||
The perhaps most advanced cookie operation libcurl offers, is saving the
|
||||
entire internal cookie state back into a Netscape/Mozilla formatted cookie
|
||||
@@ -990,7 +996,7 @@ FTP Peculiarities We Need
|
||||
|
||||
libcurl can either connect to the server a second time or tell the server to
|
||||
connect back to it. The first option is the default and it is also what works
|
||||
best for all the people behind firewalls, NATs or IP-masquarading setups.
|
||||
best for all the people behind firewalls, NATs or IP-masquerading setups.
|
||||
libcurl then tells the server to open up a new port and wait for a second
|
||||
connection. This is by default attempted with EPSV first, and if that doesn't
|
||||
work it tries PASV instead. (EPSV is an extension to the original FTP spec
|
||||
@@ -1063,7 +1069,7 @@ Security Considerations
|
||||
.netrc
|
||||
|
||||
.netrc is a pretty handy file/feature that allows you to login quickly and
|
||||
automaticly to frequently visited sites. The file contains passwords in
|
||||
automatically 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 mounted or used on another network
|
||||
based file system, so the clear text password will fly through your
|
||||
@@ -1077,8 +1083,8 @@ Security Considerations
|
||||
Many of the protocols libcurl supports send name and password unencrypted
|
||||
as clear text (HTTP Basic authentication, FTP, TELNET etc). It is very
|
||||
easy for anyone on your network or a network nearby yours, to just fire up
|
||||
a network analyzer tool and evesdrop on your passwords. Don't let the fact
|
||||
that HTTP uses base64 encoded passwords fool you. They may not look
|
||||
a network analyzer tool and eavesdrop on your passwords. Don't let the
|
||||
fact that HTTP uses base64 encoded passwords fool you. They may not look
|
||||
readable at a first glance, but they very easily "deciphered" by anyone
|
||||
within seconds.
|
||||
|
||||
@@ -1090,21 +1096,17 @@ Security Considerations
|
||||
Showing What You Do
|
||||
|
||||
On a related issue, be aware that even in situations like when you have
|
||||
problems with libcurl and ask somone for help, everything you reveal in
|
||||
problems with libcurl and ask someone for help, everything you reveal in
|
||||
order to get best possible help might also impose certain security related
|
||||
risks. Host names, user names, paths, operating system specifics etc (not
|
||||
to mention passwords of course) may in fact be used by intruders to gain
|
||||
additional information of a potential target.
|
||||
|
||||
To avoid this problem, you must of course use your common sense. Often,
|
||||
you can just edit out the senstive data or just rearch/replace your true
|
||||
you can just edit out the sensitive data or just search/replace your true
|
||||
information with faked data.
|
||||
|
||||
|
||||
SSL, Certificates and Other Tricks
|
||||
|
||||
[ seeding, passwords, keys, certificates, ENGINE, ca certs ]
|
||||
|
||||
Multiple Transfers Using the multi Interface
|
||||
|
||||
The easy interface as described in detail in this document is a synchronous
|
||||
@@ -1115,18 +1117,69 @@ Multiple Transfers Using the multi Interface
|
||||
multiple files in both directions at the same time, without forcing you to
|
||||
use multiple threads.
|
||||
|
||||
[fill in lots of more multi stuff here]
|
||||
To use this interface, you are better off if you first understand the basics
|
||||
of how to use the easy interface. The multi interface is simply a way to make
|
||||
multiple transfers at the same time, by adding up multiple easy handles in to
|
||||
a "multi stack".
|
||||
|
||||
Future
|
||||
You create the easy handles you want and you set all the options just like
|
||||
you have been told above, and then you create a multi handle with
|
||||
curl_multi_init() and add all those easy handles to that multi handle with
|
||||
curl_multi_add_handle().
|
||||
|
||||
[ sharing between handles, mutexes, pipelining ]
|
||||
When you've added the handles you have for the moment (you can still add new
|
||||
ones at any time), you start the transfers by call curl_multi_perform().
|
||||
|
||||
curl_multi_perform() is asynchronous. It will only execute as little as
|
||||
possible and then return back control to your program. It is designed to
|
||||
never block. If it returns CURLM_CALL_MULTI_PERFORM you better call it again
|
||||
soon, as that is a signal that it still has local data to send or remote data
|
||||
to receive.
|
||||
|
||||
The best usage of this interface is when you do a select() on all possible
|
||||
file descriptors or sockets to know when to call libcurl again. This also
|
||||
makes it easy for you to wait and respond to actions on your own
|
||||
application's sockets/handles. You figure out what to select() for by using
|
||||
curl_multi_fdset(), that fills in a set of fd_set variables for you with the
|
||||
particular file descriptors libcurl uses for the moment.
|
||||
|
||||
When you then call select(), it'll return when one of the file handles signal
|
||||
action and you then call curl_multi_perform() to allow libcurl to do what it
|
||||
wants to do. Take note that libcurl does also feature some time-out code so
|
||||
we advice you to never use very long timeouts on select() before you call
|
||||
curl_multi_perform(), which thus should be called unconditionally every now
|
||||
and then even if none of its file descriptors have signaled ready. Another
|
||||
precaution you should use: always call curl_multi_fdset() immediately before
|
||||
the select() call since the current set of file descriptors may change when
|
||||
calling a curl function.
|
||||
|
||||
If you want to stop the transfer of one of the easy handles in the stack, you
|
||||
can use curl_multi_remove_handle() to remove individual easy
|
||||
handles. Remember that easy handles should be curl_easy_cleanup()ed.
|
||||
|
||||
When a transfer within the multi stack has finished, the counter of running
|
||||
transfers (as filled in by curl_multi_perform()) will decrease. When the
|
||||
number reaches zero, all transfers are done.
|
||||
|
||||
curl_multi_info_read() can be used to get information about completed
|
||||
transfers. It then returns the CURLcode for each easy transfer, to allow you
|
||||
to figure out success on each individual transfer.
|
||||
|
||||
|
||||
SSL, Certificates and Other Tricks
|
||||
|
||||
[ seeding, passwords, keys, certificates, ENGINE, ca certs ]
|
||||
|
||||
|
||||
Sharing Data Between Easy Handles
|
||||
|
||||
[ fill in ]
|
||||
|
||||
-----
|
||||
Footnotes:
|
||||
|
||||
[1] = libcurl 7.10.3 and later have the ability to switch over to chunked
|
||||
Tranfer-Encoding in cases were HTTP uploads are done with data of an
|
||||
Transfer-Encoding in cases were HTTP uploads are done with data of an
|
||||
unknown size.
|
||||
|
||||
[2] = This happens on Windows machines when libcurl is built and used as a
|
||||
|
@@ -15,7 +15,8 @@ man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3 \
|
||||
curl_multi_perform.3 curl_multi_remove_handle.3 curl_share_cleanup.3 \
|
||||
curl_share_init.3 curl_share_setopt.3 libcurl.3 libcurl-easy.3 \
|
||||
libcurl-multi.3 libcurl-share.3 libcurl-errors.3 curl_easy_strerror.3 \
|
||||
curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3
|
||||
curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3 \
|
||||
libcurl-tutorial.3
|
||||
|
||||
HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
|
||||
curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html \
|
||||
@@ -30,7 +31,8 @@ HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
|
||||
curl_share_cleanup.html curl_share_init.html curl_share_setopt.html \
|
||||
libcurl.html libcurl-multi.html libcurl-easy.html libcurl-share.html \
|
||||
libcurl-errors.html curl_easy_strerror.html curl_multi_strerror.html \
|
||||
curl_share_strerror.html curl_global_init_mem.html
|
||||
curl_share_strerror.html curl_global_init_mem.html \
|
||||
libcurl-tutorial.html
|
||||
|
||||
PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
|
||||
curl_easy_init.pdf curl_easy_perform.pdf curl_easy_setopt.pdf \
|
||||
@@ -45,7 +47,7 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
|
||||
curl_share_init.pdf curl_share_setopt.pdf libcurl.pdf \
|
||||
libcurl-multi.pdf libcurl-easy.pdf libcurl-share.pdf \
|
||||
libcurl-errors.pdf curl_easy_strerror.pdf curl_multi_strerror.pdf \
|
||||
curl_share_strerror.pdf curl_global_init_mem.pdf
|
||||
curl_share_strerror.pdf curl_global_init_mem.pdf libcurl-tutorial.pdf
|
||||
|
||||
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
||||
|
||||
|
@@ -119,6 +119,15 @@ filled with at most \fIsize\fP multiplied with \fInmemb\fP number of
|
||||
bytes. Your function must return the actual number of bytes that you stored in
|
||||
that memory area. Returning 0 will signal end-of-file to the library and cause
|
||||
it to stop the current transfer.
|
||||
|
||||
If you stop the current transfer by returning 0 "pre-maturely" (i.e before the
|
||||
server expected it, like when you've told you will upload N bytes and you
|
||||
upload less than N bytes), you may experience that the server "hangs" waiting
|
||||
for the rest of the data that won't come.
|
||||
|
||||
In libcurl 7.12.1 and later, the read callback may return
|
||||
\fICURL_READFUNC_ABORT\fP to stop the current operation at once, with a
|
||||
\fICURLE_ABORTED_BY_CALLBACK\fP error code from the transfer.
|
||||
.IP 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
|
||||
@@ -456,6 +465,9 @@ redirections have been followed, the next redirect will cause an error
|
||||
.IP CURLOPT_PUT
|
||||
A non-zero parameter tells the library to use HTTP PUT to transfer data. The
|
||||
data should be set with \fICURLOPT_READDATA\fP and \fICURLOPT_INFILESIZE\fP.
|
||||
|
||||
This option is deprecated and starting with version 7.12.1 you should instead
|
||||
use \fICURLOPT_UPLOAD\fP.
|
||||
.IP CURLOPT_POST
|
||||
A non-zero parameter tells the library to do a regular HTTP post. This is a
|
||||
normal application/x-www-form-urlencoded kind, which is the most commonly used
|
||||
@@ -522,6 +534,8 @@ The first line in a request (usually containing a GET or POST) is not a header
|
||||
and cannot be replaced using this option. Only the lines following the
|
||||
request-line are headers.
|
||||
|
||||
Pass a NULL to this to reset back to no custom headers.
|
||||
|
||||
\fBNOTE:\fP The most commonly replaced headers have "shortcuts" in the options
|
||||
\fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
|
||||
.IP CURLOPT_HTTP200ALIASES
|
||||
@@ -692,10 +706,11 @@ want. It should be in the format "X-Y", where X or Y may be left out. HTTP
|
||||
transfers also support several intervals, separated with commas as in
|
||||
\fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP
|
||||
server to send the response document in pieces (using standard MIME separation
|
||||
techniques).
|
||||
techniques). Pass a NULL to this option to disable the use of ranges.
|
||||
.IP CURLOPT_RESUME_FROM
|
||||
Pass a long as parameter. It contains the offset in number of bytes that you
|
||||
want the transfer to start from.
|
||||
want the transfer to start from. Set this option to 0 to make the transfer
|
||||
start from the beginning (effectively disabling resume).
|
||||
.IP CURLOPT_RESUME_FROM_LARGE
|
||||
Pass an curl_off_t as parameter. It contains the offset in number of bytes
|
||||
that you want the transfer to start from. (Added in 7.11.0)
|
||||
@@ -734,7 +749,8 @@ as a curl_off_t. (Added in 7.11.0)
|
||||
.IP CURLOPT_UPLOAD
|
||||
A non-zero parameter tells the library to prepare for an upload. The
|
||||
\fICURLOPT_READDATA\fP and \fICURLOPT_INFILESIZE_LARGE\fP are also interesting
|
||||
for uploads.
|
||||
for uploads. If the protocol is HTTP, uploading means using the PUT request
|
||||
unless you tell libcurl otherwise.
|
||||
.IP CURLOPT_MAXFILESIZE
|
||||
Pass a long as parameter. This allows you to specify the maximum size (in
|
||||
bytes) of a file to download. If the file requested is larger than this value,
|
||||
@@ -960,5 +976,9 @@ standard for details.
|
||||
CURLE_OK (zero) means that the option was set properly, non-zero means an
|
||||
error occurred as \fI<curl/curl.h>\fP defines. See the \fIlibcurl-errors(3)\fP
|
||||
man page for the full list with descriptions.
|
||||
|
||||
If you try to set an option that libcurl doesn't know about, perhaps because
|
||||
the library is too old to support it or the option was removed in a recent
|
||||
version, this function will return \fICURLE_FAILED_INIT\fP.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_easy_init "(3), " curl_easy_cleanup "(3), "
|
||||
|
@@ -205,5 +205,4 @@ defines.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_easy_setopt "(3), "
|
||||
.BR curl_formparse "(3) [deprecated], "
|
||||
.BR curl_formfree "(3)"
|
||||
|
@@ -16,7 +16,7 @@
|
||||
<br><a href="libcurl-multi.html">libcurl-multi</a>
|
||||
<br><a href="libcurl-share.html">libcurl-share</a>
|
||||
<br><a href="libcurl-errors.html">libcurl-errors</a>
|
||||
<br><a href="../libcurl-the-guide">libcurl-the-guide</a> (plain text)
|
||||
<br><a href="libcurl-tutorial.html">libcurl-tutorial</a>
|
||||
|
||||
<H2>Library Functions (A-Z)</H2>
|
||||
<a href="curl_easy_cleanup.html">curl_easy_cleanup</A>
|
||||
@@ -34,6 +34,7 @@
|
||||
<br><a href="curl_getenv.html">curl_getenv</A>
|
||||
<br><a href="curl_global_cleanup.html">curl_global_cleanup</A>
|
||||
<br><a href="curl_global_init.html">curl_global_init</A>
|
||||
<br><a href="curl_global_init_mem.html">curl_global_init_mem</A>
|
||||
<br><a href="curl_mprintf.html">curl_mprintf</A>
|
||||
<br><a href="curl_multi_add_handle.html">curl_multi_add_handle</a>
|
||||
<br><a href="curl_multi_cleanup.html">curl_multi_cleanup</a>
|
||||
|
@@ -8,9 +8,9 @@ libcurl-multi \- how to use the multi interface
|
||||
.SH DESCRIPTION
|
||||
This is an overview on how to use the libcurl multi interface in your C
|
||||
programs. There are specific man pages for each function mentioned in
|
||||
here. There's also the libcurl-the-guide document for a complete tutorial to
|
||||
programming with libcurl and the \fIlibcurl(3)\fP man page for an overview of
|
||||
the libcurl easy interface.
|
||||
here. There's also the \fIlibcurl-tutorial(3)f\P man page for a complete
|
||||
tutorial to programming with libcurl and the \fIlibcurl-easy(3)\fP man page
|
||||
for an overview of the libcurl easy interface.
|
||||
|
||||
All functions in the multi interface are prefixed with curl_multi.
|
||||
.SH "PLEASE NOTICE"
|
||||
|
1171
docs/libcurl/libcurl-tutorial.3
Normal file
1171
docs/libcurl/libcurl-tutorial.3
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,17 @@
|
||||
.\" You can view this file with:
|
||||
.\" nroff -man [file]
|
||||
.\" $Id$
|
||||
.\"
|
||||
.TH libcurl 3 "19 March 2002" "libcurl 7.9.6" "libcurl overview"
|
||||
.SH NAME
|
||||
libcurl \- client-side URL transfers
|
||||
.SH DESCRIPTION
|
||||
This is an overview on how to use libcurl in your C programs. There are
|
||||
This is an short overview on how to use libcurl in your C programs. There are
|
||||
specific man pages for each function mentioned in here. There are also the
|
||||
\fIlibcurl-easy(3)\fP man page, the \fIlibcurl-multi(3)\fP man page, the
|
||||
\fIlibcurl-share(3)\fP man page and the \fIlibcurl-the-guide\fP document for
|
||||
further reading on how to do programming with libcurl.
|
||||
\fIlibcurl-share(3)\fP man page and the \fIlibcurl-tutorial(3)\fP man page for
|
||||
in-depth understanding on how to program with libcurl.
|
||||
|
||||
There exist more than a dozen custom bindings that bring libcurl access to
|
||||
your favourite language. Look elsewhere for documentation on those.
|
||||
There are more than a twenty custom bindings available that bring libcurl
|
||||
access to your favourite language. Look elsewhere for documentation on those.
|
||||
|
||||
All applications that use libcurl should call \fIcurl_global_init(3)\fP
|
||||
exactly once before any libcurl function can be used. After all usage of
|
||||
|
@@ -52,11 +52,11 @@ extern "C" {
|
||||
* platforms. We also provide a CURL_FORMAT_OFF_T define to use in *printf
|
||||
* format strings when outputting a variable of type curl_off_t.
|
||||
*/
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(__LCC__)
|
||||
/* MSVC */
|
||||
typedef signed __int64 curl_off_t;
|
||||
#define CURL_FORMAT_OFF_T "%I64d"
|
||||
#else /* MSC_VER */
|
||||
#else /* _MSC_VER || __LCC__ */
|
||||
#if (defined(__GNUC__) && defined(WIN32)) || defined(__WATCOMC__)
|
||||
/* gcc on windows or Watcom */
|
||||
typedef long long curl_off_t;
|
||||
@@ -88,7 +88,7 @@ extern "C" {
|
||||
#define CURL_FORMAT_OFF_T "%ld"
|
||||
#endif
|
||||
#endif /* GCC or Watcom on Windows */
|
||||
#endif /* MSC_VER */
|
||||
#endif /* _MSC_VER || __LCC__ */
|
||||
|
||||
#ifdef UNDEF_FILE_OFFSET_BITS
|
||||
/* this was defined above for our checks, undefine it again */
|
||||
@@ -143,6 +143,9 @@ typedef size_t (*curl_write_callback)(char *buffer,
|
||||
size_t nitems,
|
||||
void *outstream);
|
||||
|
||||
/* This is a brand new return code for the read callback that will signal
|
||||
the caller to immediately abort the current transfer. */
|
||||
#define CURL_READFUNC_ABORT 0x10000000
|
||||
typedef size_t (*curl_read_callback)(char *buffer,
|
||||
size_t size,
|
||||
size_t nitems,
|
||||
@@ -173,6 +176,8 @@ typedef enum {
|
||||
CURLINFO_HEADER_OUT, /* 2 */
|
||||
CURLINFO_DATA_IN, /* 3 */
|
||||
CURLINFO_DATA_OUT, /* 4 */
|
||||
CURLINFO_SSL_DATA_IN, /* 5 */
|
||||
CURLINFO_SSL_DATA_OUT, /* 6 */
|
||||
CURLINFO_END
|
||||
} curl_infotype;
|
||||
|
||||
@@ -327,7 +332,7 @@ typedef enum {
|
||||
* platforms.
|
||||
*/
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
|
||||
defined(__HP_aCC) || defined(__BORLANDC__)
|
||||
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__)
|
||||
/* This compiler is believed to have an ISO compatible preprocessor */
|
||||
#define CURL_ISOCPP
|
||||
#else
|
||||
@@ -518,7 +523,7 @@ typedef enum {
|
||||
CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
|
||||
|
||||
CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
|
||||
CINIT(PUT, LONG, 54), /* PUT the input file */
|
||||
CINIT(PUT, LONG, 54), /* HTTP PUT */
|
||||
|
||||
/* 55 = OBSOLETE */
|
||||
|
||||
@@ -564,9 +569,9 @@ typedef enum {
|
||||
/* Maximum number of http redirects to follow */
|
||||
CINIT(MAXREDIRS, LONG, 68),
|
||||
|
||||
/* Pass a pointer to a time_t to get a possible date of the requested
|
||||
document! Pass a NULL to shut it off. */
|
||||
CINIT(FILETIME, OBJECTPOINT, 69),
|
||||
/* Pass a long set to 1 to get the date of the requested document (if
|
||||
possible)! Pass a zero to shut it off. */
|
||||
CINIT(FILETIME, LONG, 69),
|
||||
|
||||
/* This points to a linked list of telnet options */
|
||||
CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
|
||||
@@ -780,6 +785,34 @@ typedef enum {
|
||||
/* Enable/disable the TCP Nagle algorithm */
|
||||
CINIT(TCP_NODELAY, LONG, 121),
|
||||
|
||||
/* When doing 3rd party transfer, set the source host name with this */
|
||||
CINIT(SOURCE_HOST, OBJECTPOINT, 122),
|
||||
|
||||
/* When doing 3rd party transfer, set the source user and password with
|
||||
this */
|
||||
CINIT(SOURCE_USERPWD, OBJECTPOINT, 123),
|
||||
|
||||
/* When doing 3rd party transfer, set the source file path with this */
|
||||
CINIT(SOURCE_PATH, OBJECTPOINT, 124),
|
||||
|
||||
/* When doing 3rd party transfer, set the source server's port number
|
||||
with this */
|
||||
CINIT(SOURCE_PORT, LONG, 125),
|
||||
|
||||
/* When doing 3rd party transfer, decide which server that should get the
|
||||
PASV command (and the other gets the PORT).
|
||||
0 (default) - The target host issues PASV.
|
||||
1 - The source host issues PASV */
|
||||
CINIT(PASV_HOST, LONG, 126),
|
||||
|
||||
/* When doing 3rd party transfer, set the source pre-quote linked list
|
||||
of commands with this */
|
||||
CINIT(SOURCE_PREQUOTE, OBJECTPOINT, 127),
|
||||
|
||||
/* When doing 3rd party transfer, set the source post-quote linked list
|
||||
of commands with this */
|
||||
CINIT(SOURCE_POSTQUOTE, OBJECTPOINT, 128),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -937,6 +970,7 @@ typedef enum {
|
||||
CURL_FORMADD_UNKNOWN_OPTION,
|
||||
CURL_FORMADD_INCOMPLETE,
|
||||
CURL_FORMADD_ILLEGAL_ARRAY,
|
||||
CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
|
||||
|
||||
CURL_FORMADD_LAST /* last */
|
||||
} CURLFORMcode;
|
||||
|
@@ -28,7 +28,7 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.12.0-CVS"
|
||||
#define LIBCURL_VERSION "7.12.1-CVS"
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
@@ -44,12 +44,12 @@
|
||||
always a greater number in a more recent release. It makes comparisons with
|
||||
greater than and less than work.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x070c00
|
||||
#define LIBCURL_VERSION_NUM 0x070c01
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 12
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
||||
|
@@ -106,7 +106,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
|
||||
libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS)
|
||||
|
||||
WIN32SOURCES = $(CSOURCES)
|
||||
WIN32SOURCES = $(CSOURCES) libcurl.def
|
||||
WIN32HEADERS = $(HHEADERS) config-win32.h
|
||||
|
||||
BUILT_SOURCES = $(srcdir)/getdate.c $(top_builddir)/lib/ca-bundle.h
|
||||
|
@@ -47,7 +47,8 @@ libcurl_a_SOURCES = arpa_telnet.h file.c netrc.h timeval.c base64.c \
|
||||
strtok.c connect.c hash.c llist.c multi.c share.c share.h \
|
||||
content_encoding.h content_encoding.c http_digest.h http_digest.c \
|
||||
http_negotiate.c http_negotiate.h http_ntlm.c http_ntlm.h md5.h \
|
||||
md5.c strtoofft.c inet_pton.c
|
||||
md5.c strtoofft.c inet_pton.c strerror.c hostares.c hostasyn.c \
|
||||
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c
|
||||
|
||||
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
|
||||
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
|
||||
@@ -56,7 +57,8 @@ libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
|
||||
strequal.o easy.o security.o krb4.o memdebug.o http_chunks.o \
|
||||
strtok.o connect.o hash.o llist.o multi.o share.o \
|
||||
content_encoding.o http_digest.o http_negotiate.o http_ntlm.o md5.o \
|
||||
strtoofft.o inet_pton.o
|
||||
strtoofft.o inet_pton.o strerror.o hostares.o hostasyn.o hostip4.o \
|
||||
hostip6.o hostsyn.o hostthre.o inet_ntop.o
|
||||
|
||||
LIBRARIES = $(libcurl_a_LIBRARIES)
|
||||
SOURCES = $(libcurl_a_SOURCES)
|
||||
|
@@ -8,11 +8,13 @@
|
||||
#################################################################
|
||||
|
||||
# Edit the path below to point to the base of your Novell NDK.
|
||||
BASE = c:/novell
|
||||
INSTDIR = s:/libcurl
|
||||
ifndef NDKBASE
|
||||
NDKBASE = c:/novell
|
||||
endif
|
||||
INSTDIR = ..\curl-$(LIBCURL_VERSION_STR)-bin-nw
|
||||
|
||||
# Edit the path below to point to the base of your Zlib sources.
|
||||
ZLIB_PATH = ../../../cw/zlib-src-1.1.4
|
||||
#ZLIB_PATH = ../../zlib-1.2.1
|
||||
|
||||
# Edit the vars below to change NLM target settings.
|
||||
TARGET = libcurl
|
||||
@@ -22,7 +24,6 @@ DESCR = cURL libcurl $(LIBCURL_VERSION_STR) - http://curl.haxx.se
|
||||
MTSAFE = YES
|
||||
STACK = 64000
|
||||
SCREEN = none
|
||||
#MODULES = libz.nlm
|
||||
EXPORTS = @libcurl.imp
|
||||
|
||||
# Edit the var below to point to your lib architecture.
|
||||
@@ -33,6 +34,7 @@ endif
|
||||
# must be equal to DEBUG or NDEBUG
|
||||
DB = NDEBUG
|
||||
# DB = DEBUG
|
||||
# DB = CURLDEBUG
|
||||
# Optimization: -O<n> or debugging: -g
|
||||
ifeq ($(DB),NDEBUG)
|
||||
OPT = -O2
|
||||
@@ -42,7 +44,7 @@ else
|
||||
OBJDIR = debug
|
||||
endif
|
||||
|
||||
# Include the version info retrieved from jk_version.h
|
||||
# Include the version info retrieved from curlver.h
|
||||
-include $(OBJDIR)/version.inc
|
||||
|
||||
# The following line defines your compiler.
|
||||
@@ -51,36 +53,39 @@ ifdef METROWERKS
|
||||
else
|
||||
CC = gcc
|
||||
endif
|
||||
CP = cp -afv
|
||||
# RM = rm -f
|
||||
# CP = cp -fv
|
||||
# if you want to mark the target as MTSAFE you will need a tool for
|
||||
# generating the xdc data for the linker; here's a minimal tool:
|
||||
# http://www.gknw.de/development/prgtools/mkxdc.zip
|
||||
# http://www.gknw.com/development/prgtools/mkxdc.zip
|
||||
MPKXDC = mkxdc
|
||||
|
||||
# Global flags for all compilers
|
||||
CFLAGS = $(OPT) -D$(DB) -DNETWARE -nostdinc
|
||||
#CFLAGS += -DHAVE_LIBZ
|
||||
|
||||
ifeq ($(CC),mwccnlm)
|
||||
LD = mwldnlm
|
||||
LDFLAGS = -nostdlib $(PRELUDE) $(OBJDIR)/*.o -o $(OBJDIR)/$(TARGET).nlm -commandfile
|
||||
CFLAGS += -gccinc -inline off -opt nointrinsics
|
||||
AR = mwldnlm
|
||||
ARFLAGS = -type library -w nocmdline $(OBJDIR)/*.o -o
|
||||
CFLAGS += -msgstyle gcc -gccinc -inline off -opt nointrinsics -proc 586
|
||||
CFLAGS += -relax_pointers
|
||||
#CFLAGS += -w on
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
PRELUDE = $(SDK_LIBC)/imports/libcpre.o
|
||||
CFLAGS += -align 4 -inst mmx -proc 686
|
||||
CFLAGS += -align 4
|
||||
CFLAGS += -D_POSIX_SOURCE
|
||||
# CFLAGS += -D__ANSIC__
|
||||
else
|
||||
PRELUDE = "$(METROWERKS)/Novell Support/libraries/runtime/prelude.obj"
|
||||
# CFLAGS += -include "$(METROWERKS)/Novell Support/headers/nlm_prefix.h"
|
||||
CFLAGS += -align 1 -proc 586
|
||||
CFLAGS += -align 1
|
||||
endif
|
||||
else
|
||||
LD = nlmconv
|
||||
LDFLAGS = -T
|
||||
AR = ar
|
||||
ARFLAGS = -cq
|
||||
CFLAGS += -fno-builtin -fpack-struct -fpcc-struct-return
|
||||
CFLAGS += -Wall # -pedantic
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
@@ -89,40 +94,51 @@ ifeq ($(LIBARCH),LIBC)
|
||||
# CFLAGS += -D__ANSIC__
|
||||
else
|
||||
PRELUDE = $(SDK_CLIB)/imports/clibpre.gcc.o
|
||||
CFLAGS += -include $(BASE)/nlmconv/genlm.h
|
||||
CFLAGS += -include $(NDKBASE)/nlmconv/genlm.h
|
||||
endif
|
||||
endif
|
||||
|
||||
LDLIBS =
|
||||
|
||||
NDK_ROOT = $(BASE)/ndk
|
||||
NDK_ROOT = $(NDKBASE)/ndk
|
||||
SDK_CLIB = $(NDK_ROOT)/nwsdk
|
||||
SDK_LIBC = $(NDK_ROOT)/libc
|
||||
SDK_LDAP = $(NDK_ROOT)/cldapsdk/netware
|
||||
CURL_INC = ../include
|
||||
|
||||
INCLUDES = -I$(CURL_INC)
|
||||
INCLUDES += -I$(ZLIB_PATH)
|
||||
INCLUDES = -I. -I../include
|
||||
|
||||
ifdef ZLIB_PATH
|
||||
INCLUDES += -I$(ZLIB_PATH)
|
||||
CFLAGS += -DHAVE_ZLIB_H -DHAVE_LIBZ
|
||||
IMPORTS = @$(ZLIB_PATH)/nw/zlib.imp
|
||||
MODULES = libz.nlm
|
||||
endif
|
||||
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
INCLUDES += -I$(SDK_LIBC)/include -I$(SDK_LIBC)/include/nks
|
||||
INCLUDES += -I$(SDK_LIBC)/include/winsock
|
||||
INCLUDES += -I$(SDK_LDAP)/libc/inc
|
||||
# INCLUDES += -I$(SDK_LDAP)/libc/inc
|
||||
else
|
||||
INCLUDES += -I$(SDK_CLIB)/include/nlm -I$(SDK_CLIB)/include
|
||||
# INCLUDES += -I$(SDK_CLIB)/include/nlm/obsolete
|
||||
INCLUDES += -I$(SDK_LDAP)/clib/inc
|
||||
# INCLUDES += -I$(SDK_LDAP)/clib/inc
|
||||
CFLAGS += -DNETDB_USE_INTERNET
|
||||
endif
|
||||
CFLAGS += $(INCLUDES)
|
||||
|
||||
ifeq ($(MTSAFE),YES)
|
||||
XDCOPT = -n
|
||||
endif
|
||||
ifeq ($(MTSAFE),NO)
|
||||
XDCOPT = -u
|
||||
endif
|
||||
ifdef XDCOPT
|
||||
XDCDATA = $(OBJDIR)/$(TARGET).xdc
|
||||
endif
|
||||
|
||||
ifeq ($(OSTYPE),linux)
|
||||
DL = '
|
||||
-include $(BASE)/nlmconv/ncpfs.inc
|
||||
#-include $(NDKBASE)/nlmconv/ncpfs.inc
|
||||
endif
|
||||
|
||||
OBJS = \
|
||||
@@ -169,35 +185,57 @@ OBJS = \
|
||||
$(OBJDIR)/http_ntlm.o \
|
||||
$(OBJDIR)/md5.o \
|
||||
$(OBJDIR)/strtoofft.o \
|
||||
$(OBJDIR)/nwlib.o
|
||||
$(OBJDIR)/strerror.o \
|
||||
$(OBJDIR)/hostares.o \
|
||||
$(OBJDIR)/hostasyn.o \
|
||||
$(OBJDIR)/hostip4.o \
|
||||
$(OBJDIR)/hostip6.o \
|
||||
$(OBJDIR)/hostsyn.o \
|
||||
$(OBJDIR)/hostthre.o \
|
||||
$(OBJDIR)/inet_ntop.o \
|
||||
|
||||
OBJL = $(OBJS) $(OBJDIR)/nwlib.o
|
||||
|
||||
all: $(OBJDIR) $(OBJDIR)/version.inc $(OBJDIR)/$(TARGET).nlm
|
||||
nlm: $(OBJDIR) $(OBJDIR)/version.inc $(OBJDIR)/$(TARGET).nlm
|
||||
|
||||
lib: $(OBJDIR) $(OBJDIR)/$(TARGET).lib
|
||||
|
||||
all: lib nlm
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@echo Compiling $<
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
# @echo Compiling $<
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/version.inc: $(CURL_INC)/curl/curl.h $(OBJDIR)
|
||||
$(OBJDIR)/version.inc: ../include/curl/curlver.h $(OBJDIR)
|
||||
@echo Creating $@
|
||||
@awk -f ../packages/netware/get_ver.awk $< > $@
|
||||
@awk -f ../packages/NetWare/get_ver.awk $< > $@
|
||||
|
||||
dist: all
|
||||
-$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(TARGET).map $(OBJDIR)/$(TARGET).ncv
|
||||
-$(RM) $(OBJDIR)/$(TARGET).def $(OBJDIR)/version.inc $(XDCDATA)
|
||||
# -$(CP) ../changes.txt $(OBJDIR)/
|
||||
|
||||
install: all
|
||||
@[ -d $(INSTDIR) ] || mkdir $(INSTDIR)
|
||||
install: $(INSTDIR) all
|
||||
@$(CP) $(TARGET).nlm $(INSTDIR)
|
||||
@$(CP) ../CHANGES $(INSTDIR)
|
||||
@$(CP) ../COPYING $(INSTDIR)
|
||||
@$(CP) ../README $(INSTDIR)
|
||||
@$(CP) ../RELEASE-NOTES $(INSTDIR)
|
||||
|
||||
clean:
|
||||
-$(RM) -r $(OBJDIR)
|
||||
|
||||
$(INSTDIR):
|
||||
@mkdir $(INSTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
@mkdir $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/$(TARGET).nlm: $(OBJS) $(OBJDIR)/$(TARGET).def $(XDCDATA)
|
||||
$(OBJDIR)/$(TARGET).lib: $(OBJS)
|
||||
@echo Creating $@
|
||||
@-$(RM) $@
|
||||
@$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
$(OBJDIR)/$(TARGET).nlm: $(OBJL) $(OBJDIR)/$(TARGET).def $(XDCDATA)
|
||||
@echo Linking $@
|
||||
@-$(RM) $@
|
||||
@$(LD) $(LDFLAGS) $(OBJDIR)/$(TARGET).def
|
||||
@@ -239,25 +277,21 @@ ifeq ($(LIBARCH),CLIB)
|
||||
@echo $(DL)import @$(SDK_CLIB)/imports/threads.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_CLIB)/imports/nlmlib.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_CLIB)/imports/socklib.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapsdk.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapssl.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapx.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapsdk.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapssl.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapx.imp$(DL) >> $@
|
||||
@echo $(DL)module clib$(DL) >> $@
|
||||
else
|
||||
ifeq ($(LD),nlmconv)
|
||||
@echo $(DL)flag_on 64$(DL) >> $@
|
||||
else
|
||||
@echo $(DL)autounload$(DL) >> $@
|
||||
endif
|
||||
@echo $(DL)pseudopreemption$(DL) >> $@
|
||||
@echo $(DL)start _LibCPrelude$(DL) >> $@
|
||||
@echo $(DL)exit _LibCPostlude$(DL) >> $@
|
||||
@echo $(DL)check _LibCCheckUnload$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LIBC)/imports/libc.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LIBC)/imports/netware.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapsdk.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapssl.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapx.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapsdk.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapssl.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapx.imp$(DL) >> $@
|
||||
@echo $(DL)module libc$(DL) >> $@
|
||||
endif
|
||||
ifdef MODULES
|
||||
@@ -275,3 +309,18 @@ ifeq ($(LD),nlmconv)
|
||||
@echo $(DL)output $(TARGET).nlm$(DL) >> $@
|
||||
endif
|
||||
|
||||
ca-bundle.h: Makefile.netware
|
||||
@echo Creating $@
|
||||
@echo $(DL)/* Do not edit this file - it is created by make!$(DL) > $@
|
||||
@echo $(DL)** All your changes will be lost!!$(DL) >> $@
|
||||
@echo $(DL)*/$(DL) >> $@
|
||||
@echo $(DL)#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")$(DL) >> $@
|
||||
|
||||
getdate.c: getdate.c.cvs
|
||||
@echo Creating $@
|
||||
@-$(RM) getdate.y
|
||||
@$(CP) $< $@
|
||||
|
||||
url.c: ca-bundle.h
|
||||
|
||||
|
||||
|
@@ -182,10 +182,6 @@
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
#undef HAVE_LIBSSL
|
||||
|
||||
/* If zlib is available */
|
||||
#undef HAVE_LIBZ
|
||||
//#define HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
@@ -396,14 +392,17 @@
|
||||
/* Define to 1 if you have the <x509.h> header file. */
|
||||
#undef HAVE_X509_H
|
||||
|
||||
/* if you have the zlib.h header file */
|
||||
#define HAVE_ZLIB_H 1
|
||||
/* if you have the zlib.h header file - set from Makefile */
|
||||
/* #undef HAVE_ZLIB_H */
|
||||
|
||||
/* If zlib is available - set from Makefile */
|
||||
/* #undef HAVE_LIBZ */
|
||||
|
||||
/* need REENTRANT defined */
|
||||
#undef NEED_REENTRANT
|
||||
|
||||
/* cpu-machine-OS */
|
||||
#define OS "i386-pc-NetWare"
|
||||
#define OS "i586-pc-NetWare"
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
@@ -1,6 +1,9 @@
|
||||
/* config.h. Generated automatically by configure. */
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
#ifndef __CONFIG_WIN32_H
|
||||
#define __CONFIG_WIN32_H
|
||||
|
||||
/* Define if on AIX 3.
|
||||
System headers sometimes define this.
|
||||
We just want to avoid a redefinition error message. */
|
||||
@@ -223,9 +226,12 @@
|
||||
/*************************************************
|
||||
* This section is for compiler specific defines.*
|
||||
*************************************************/
|
||||
#if defined(MINGW32) || defined(__WATCOMC__) /* Borland and MS don't have this */
|
||||
/* Borland and MS don't have this */
|
||||
#if defined(MINGW32) || defined(__WATCOMC__) || defined(__LCC__)
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
128
lib/connect.c
128
lib/connect.c
@@ -490,8 +490,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
/* check for connect without timeout as we want to return immediately */
|
||||
rc = waitconnect(sockfd, 0);
|
||||
|
||||
if(0 == rc) {
|
||||
if (verifyconnect(sockfd,NULL)) {
|
||||
if(WAITCONN_CONNECTED == rc) {
|
||||
if (verifyconnect(sockfd, NULL)) {
|
||||
/* we are connected, awesome! */
|
||||
*connected = TRUE;
|
||||
return CURLE_OK;
|
||||
@@ -500,25 +500,22 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
failf(data, "Connection failed");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
else if(1 != rc) {
|
||||
else if(WAITCONN_TIMEOUT != rc) {
|
||||
int error = Curl_ourerrno();
|
||||
failf(data, "Failed connect to %s:%d; %s",
|
||||
conn->host.name, conn->port, Curl_strerror(conn,error));
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
/*
|
||||
* If the connection phase is "done" here, we should attempt to connect
|
||||
* to the "next address" in the Curl_hostaddr structure that we resolved
|
||||
* before. But we don't have that struct around anymore and we can't just
|
||||
* keep a pointer since the cache might in fact have gotten pruned by the
|
||||
* time we want to read this... Alas, we don't do this yet.
|
||||
* If the connection failed here, we should attempt to connect to the "next
|
||||
* address" for the given host.
|
||||
*/
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static void Curl_setNoDelay(struct connectdata *conn,
|
||||
curl_socket_t sockfd)
|
||||
static void tcpnodelay(struct connectdata *conn,
|
||||
curl_socket_t sockfd)
|
||||
{
|
||||
#ifdef TCP_NODELAY
|
||||
struct SessionHandle *data= conn->data;
|
||||
@@ -549,22 +546,22 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
bool *connected) /* really connected? */
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
curl_socket_t sockfd = CURL_SOCKET_BAD;
|
||||
int rc, error;
|
||||
curl_socket_t sockfd= CURL_SOCKET_BAD;
|
||||
int aliasindex=0;
|
||||
char *hostname;
|
||||
int aliasindex;
|
||||
int num_addr;
|
||||
bool conected;
|
||||
char addr_buf[256];
|
||||
|
||||
Curl_ipconnect *curr_addr;
|
||||
struct timeval after;
|
||||
struct timeval before = Curl_tvnow();
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
struct addrinfo *ai;
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
* Figure out what maximum time we have left
|
||||
*************************************************************/
|
||||
long timeout_ms=300000; /* milliseconds, default to five minutes */
|
||||
long timeout_ms=300000; /* milliseconds, default to five minutes total */
|
||||
long timeout_per_addr;
|
||||
|
||||
*connected = FALSE; /* default to not connected */
|
||||
|
||||
@@ -600,31 +597,35 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
}
|
||||
}
|
||||
|
||||
hostname = data->change.proxy?conn->proxy.name:conn->host.name;
|
||||
infof(data, "About to connect() to %s port %d\n",
|
||||
hostname, port);
|
||||
/* Max time for each address */
|
||||
num_addr = Curl_num_addresses(remotehost->addr);
|
||||
timeout_per_addr = timeout_ms / num_addr;
|
||||
|
||||
/* Below is the loop that attempts to connect to all IP-addresses we
|
||||
* know for the given host. One by one until one IP succeedes.
|
||||
*/
|
||||
#ifdef ENABLE_IPV6
|
||||
/*
|
||||
* Connecting with a getaddrinfo chain
|
||||
*/
|
||||
for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) {
|
||||
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (sockfd == CURL_SOCKET_BAD)
|
||||
(void)port; /* the port number is already included in the getaddrinfo
|
||||
struct */
|
||||
for (curr_addr = remotehost->addr, aliasindex=0; curr_addr;
|
||||
curr_addr = curr_addr->ai_next, aliasindex++) {
|
||||
sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype,
|
||||
curr_addr->ai_protocol);
|
||||
if (sockfd == CURL_SOCKET_BAD) {
|
||||
timeout_per_addr += timeout_per_addr / (num_addr - aliasindex);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if(data->set.tcp_nodelay)
|
||||
Curl_setNoDelay(conn, sockfd);
|
||||
#else
|
||||
/*
|
||||
* Connecting with old style IPv4-only support
|
||||
*/
|
||||
|
||||
/* This is the loop that attempts to connect to all IP-addresses we
|
||||
know for the given host. One by one. */
|
||||
for(rc=-1, aliasindex=0;
|
||||
rc && (struct in_addr *)remotehost->addr->h_addr_list[aliasindex];
|
||||
aliasindex++) {
|
||||
curr_addr = (Curl_ipconnect*)remotehost->addr->h_addr_list[0];
|
||||
for(aliasindex=0; curr_addr;
|
||||
curr_addr=(Curl_ipconnect*)remotehost->addr->h_addr_list[++aliasindex]) {
|
||||
struct sockaddr_in serv_addr;
|
||||
|
||||
/* create an IPv4 TCP socket */
|
||||
@@ -634,18 +635,21 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
return CURLE_COULDNT_CONNECT; /* big time error */
|
||||
}
|
||||
|
||||
else if(data->set.tcp_nodelay)
|
||||
Curl_setNoDelay(conn, sockfd);
|
||||
|
||||
/* nasty address work before connect can be made */
|
||||
memset((char *) &serv_addr, '\0', sizeof(serv_addr));
|
||||
memcpy((char *)&(serv_addr.sin_addr),
|
||||
(struct in_addr *)remotehost->addr->h_addr_list[aliasindex],
|
||||
memcpy((char *)&(serv_addr.sin_addr), curr_addr,
|
||||
sizeof(struct in_addr));
|
||||
serv_addr.sin_family = remotehost->addr->h_addrtype;
|
||||
serv_addr.sin_port = htons((unsigned short)port);
|
||||
#endif
|
||||
|
||||
|
||||
Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf));
|
||||
infof(data, " Trying %s... ", addr_buf);
|
||||
|
||||
if(data->set.tcp_nodelay)
|
||||
tcpnodelay(conn, sockfd);
|
||||
|
||||
if(conn->data->set.device) {
|
||||
/* user selected to bind the outgoing socket to a specified "device"
|
||||
before doing connect */
|
||||
@@ -661,7 +665,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
a defined macro on some platforms and some compilers don't like to mix
|
||||
#ifdefs with macro usage! (AmigaOS is one such platform) */
|
||||
#ifdef ENABLE_IPV6
|
||||
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
|
||||
rc = connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen);
|
||||
#else
|
||||
rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||
#endif
|
||||
@@ -682,38 +686,39 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
/* asynchronous connect, wait for connect or timeout */
|
||||
if(data->state.used_interface == Curl_if_multi)
|
||||
/* don't hang when doing multi */
|
||||
timeout_ms = 0;
|
||||
timeout_per_addr = timeout_ms = 0;
|
||||
|
||||
rc = waitconnect(sockfd, timeout_ms);
|
||||
rc = waitconnect(sockfd, timeout_per_addr);
|
||||
break;
|
||||
default:
|
||||
/* unknown error, fallthrough and try another address! */
|
||||
failf(data, "Failed to connect to %s IP number %d: %s",
|
||||
hostname, aliasindex+1, Curl_strerror(conn,error));
|
||||
failf(data, "Failed to connect to %s (IP number %d): %s",
|
||||
addr_buf, aliasindex+1, Curl_strerror(conn,error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The '1 == rc' comes from the waitconnect(), and not from connect().
|
||||
We can be sure of this since connect() cannot return 1. */
|
||||
if((1 == rc) && (data->state.used_interface == Curl_if_multi)) {
|
||||
/* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
|
||||
connect(). We can be sure of this since connect() cannot return 1. */
|
||||
if((WAITCONN_TIMEOUT == rc) &&
|
||||
(data->state.used_interface == Curl_if_multi)) {
|
||||
/* Timeout when running the multi interface, we return here with a
|
||||
CURLE_OK return code. */
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(0 == rc) {
|
||||
if (verifyconnect(sockfd,NULL)) {
|
||||
/* we are connected, awesome! */
|
||||
*connected = TRUE; /* this is a true connect */
|
||||
break;
|
||||
}
|
||||
/* nope, not connected for real */
|
||||
rc = -1;
|
||||
conected = verifyconnect(sockfd, &error);
|
||||
|
||||
if(!rc && conected) {
|
||||
/* we are connected, awesome! */
|
||||
*connected = TRUE; /* this is a true connect */
|
||||
break;
|
||||
}
|
||||
if(WAITCONN_TIMEOUT == rc)
|
||||
infof(data, "Timeout\n");
|
||||
else
|
||||
verifyconnect(sockfd,&error); /* get non-blocking error */
|
||||
infof(data, "%s\n", Curl_strerror(conn, error));
|
||||
|
||||
/* connect failed or timed out */
|
||||
sclose(sockfd);
|
||||
@@ -727,24 +732,19 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
return CURLE_OPERATION_TIMEOUTED;
|
||||
}
|
||||
before = after;
|
||||
}
|
||||
} /* end of connect-to-each-address loop */
|
||||
|
||||
if (sockfd == CURL_SOCKET_BAD) {
|
||||
/* no good connect was made */
|
||||
*sockconn = -1;
|
||||
failf(data, "Connect failed; %s", Curl_strerror(conn,error));
|
||||
*sockconn = CURL_SOCKET_BAD;
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* leave the socket in non-blocking mode */
|
||||
|
||||
/* store the address we use */
|
||||
if(addr) {
|
||||
#ifdef ENABLE_IPV6
|
||||
*addr = ai;
|
||||
#else
|
||||
*addr = (struct in_addr *)remotehost->addr->h_addr_list[aliasindex];
|
||||
#endif
|
||||
}
|
||||
if(addr)
|
||||
*addr = curr_addr;
|
||||
|
||||
/* allow NULL-pointers to get passed in */
|
||||
if(sockconn)
|
||||
|
11
lib/cookie.c
11
lib/cookie.c
@@ -149,7 +149,7 @@ Curl_cookie_add(struct SessionHandle *data,
|
||||
unless set */
|
||||
{
|
||||
struct Cookie *clist;
|
||||
char what[MAX_COOKIE_LINE];
|
||||
char *what;
|
||||
char name[MAX_NAME];
|
||||
char *ptr;
|
||||
char *semiptr;
|
||||
@@ -167,6 +167,13 @@ Curl_cookie_add(struct SessionHandle *data,
|
||||
if(httpheader) {
|
||||
/* This line was read off a HTTP-header */
|
||||
char *sep;
|
||||
|
||||
what = malloc(MAX_COOKIE_LINE);
|
||||
if(!what) {
|
||||
free(co);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
|
||||
|
||||
while(*lineptr && isspace((int)*lineptr))
|
||||
@@ -387,6 +394,8 @@ Curl_cookie_add(struct SessionHandle *data,
|
||||
}
|
||||
}
|
||||
|
||||
free(what);
|
||||
|
||||
if(badcookie || !co->name) {
|
||||
/* we didn't get a cookie name or a bad one,
|
||||
this is an illegal line, bail out */
|
||||
|
17
lib/cookie.h
17
lib/cookie.h
@@ -60,13 +60,20 @@ struct CookieInfo {
|
||||
bool newsession; /* new session, discard session cookies on load */
|
||||
};
|
||||
|
||||
/* This is the maximum line length we accept for a cookie line */
|
||||
#define MAX_COOKIE_LINE 2048
|
||||
#define MAX_COOKIE_LINE_TXT "2047"
|
||||
/* This is the maximum line length we accept for a cookie line. RFC 2109
|
||||
section 6.3 says:
|
||||
|
||||
"at least 4096 bytes per cookie (as measured by the size of the characters
|
||||
that comprise the cookie non-terminal in the syntax description of the
|
||||
Set-Cookie header)"
|
||||
|
||||
*/
|
||||
#define MAX_COOKIE_LINE 5000
|
||||
#define MAX_COOKIE_LINE_TXT "4999"
|
||||
|
||||
/* This is the maximum length of a cookie name we deal with: */
|
||||
#define MAX_NAME 256
|
||||
#define MAX_NAME_TXT "255"
|
||||
#define MAX_NAME 1024
|
||||
#define MAX_NAME_TXT "1023"
|
||||
|
||||
struct SessionHandle;
|
||||
/*
|
||||
|
@@ -333,7 +333,8 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
|
||||
/* This is a function pointer type */
|
||||
param_func = va_arg(arg, func_T );
|
||||
ret = Curl_setopt(data, tag, param_func);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
/* This is a curl_off_t type */
|
||||
param_offset = va_arg(arg, curl_off_t);
|
||||
ret = Curl_setopt(data, tag, param_offset);
|
||||
@@ -458,6 +459,7 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
outcurl->progress.flags = data->progress.flags;
|
||||
outcurl->progress.callback = data->progress.callback;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(data->cookies) {
|
||||
/* If cookies are enabled in the parent handle, we enable them
|
||||
in the clone as well! */
|
||||
@@ -469,6 +471,7 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
/* duplicate all values in 'change' */
|
||||
if(data->change.url) {
|
||||
|
@@ -175,7 +175,7 @@ CURLcode Curl_file_done(struct connectdata *conn,
|
||||
{
|
||||
struct FILEPROTO *file = conn->proto.file;
|
||||
(void)status; /* not used */
|
||||
Curl_safefree(file->path);
|
||||
Curl_safefree(file->freepath);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -218,7 +218,12 @@ static CURLcode file_upload(struct connectdata *conn)
|
||||
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||
|
||||
while (res == CURLE_OK) {
|
||||
nread = Curl_fillreadbuffer(conn, BUFSIZE);
|
||||
int readcount;
|
||||
res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
nread = (size_t)readcount;
|
||||
|
||||
if (nread <= 0)
|
||||
break;
|
||||
|
193
lib/formdata.c
193
lib/formdata.c
@@ -100,6 +100,10 @@ Content-Disposition: form-data; name="FILECONTENT"
|
||||
*/
|
||||
|
||||
#include "setup.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
/* Length of the random boundary string. */
|
||||
#define BOUNDARY_LENGTH 40
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
|
||||
@@ -108,7 +112,7 @@ Content-Disposition: form-data; name="FILECONTENT"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <curl/curl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "formdata.h"
|
||||
#include "strequal.h"
|
||||
#include "memory.h"
|
||||
@@ -119,9 +123,6 @@ Content-Disposition: form-data; name="FILECONTENT"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* Length of the random boundary string. */
|
||||
#define BOUNDARY_LENGTH 40
|
||||
|
||||
/* What kind of Content-Type to use on un-specified files with unrecognized
|
||||
extensions. */
|
||||
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
|
||||
@@ -785,9 +786,10 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
||||
* size is incremented by the chunk length, unless it is NULL
|
||||
*/
|
||||
static CURLcode AddFormData(struct FormData **formp,
|
||||
enum formtype type,
|
||||
const void *line,
|
||||
size_t length,
|
||||
size_t *size)
|
||||
curl_off_t *size)
|
||||
{
|
||||
struct FormData *newform = (struct FormData *)
|
||||
malloc(sizeof(struct FormData));
|
||||
@@ -807,6 +809,7 @@ static CURLcode AddFormData(struct FormData **formp,
|
||||
memcpy(newform->line, line, length);
|
||||
newform->length = length;
|
||||
newform->line[length]=0; /* zero terminate for easier debugging */
|
||||
newform->type = type;
|
||||
|
||||
if(*formp) {
|
||||
(*formp)->next = newform;
|
||||
@@ -815,8 +818,20 @@ static CURLcode AddFormData(struct FormData **formp,
|
||||
else
|
||||
*formp = newform;
|
||||
|
||||
if (size)
|
||||
*size += length;
|
||||
if (size) {
|
||||
if(type == FORM_DATA)
|
||||
*size += length;
|
||||
else {
|
||||
/* Since this is a file to be uploaded here, add the size of the actual
|
||||
file */
|
||||
if(!strequal("-", newform->line)) {
|
||||
struct stat file;
|
||||
if(!stat(newform->line, &file)) {
|
||||
*size += file.st_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -825,7 +840,7 @@ static CURLcode AddFormData(struct FormData **formp,
|
||||
*/
|
||||
|
||||
static CURLcode AddFormDataf(struct FormData **formp,
|
||||
size_t *size,
|
||||
curl_off_t *size,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char s[4096];
|
||||
@@ -834,39 +849,7 @@ static CURLcode AddFormDataf(struct FormData **formp,
|
||||
vsprintf(s, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return AddFormData(formp, s, 0, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_FormBoundary() creates a suitable boundary string and returns an
|
||||
* allocated one.
|
||||
*/
|
||||
char *Curl_FormBoundary(void)
|
||||
{
|
||||
char *retstring;
|
||||
static int randomizer=0; /* this is just so that two boundaries within
|
||||
the same form won't be identical */
|
||||
size_t i;
|
||||
|
||||
static char table16[]="abcdef0123456789";
|
||||
|
||||
retstring = (char *)malloc(BOUNDARY_LENGTH+1);
|
||||
|
||||
if(!retstring)
|
||||
return NULL; /* failed */
|
||||
|
||||
srand(time(NULL)+randomizer++); /* seed */
|
||||
|
||||
strcpy(retstring, "----------------------------");
|
||||
|
||||
for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
|
||||
retstring[i] = table16[rand()%16];
|
||||
|
||||
/* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
|
||||
combinations */
|
||||
retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
|
||||
|
||||
return retstring;
|
||||
return AddFormData(formp, FORM_DATA, s, 0, size);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -936,7 +919,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
struct curl_httppost *file;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
size_t size =0;
|
||||
curl_off_t size=0; /* support potentially ENORMOUS formposts */
|
||||
char *boundary;
|
||||
char *fileboundary=NULL;
|
||||
struct curl_slist* curList;
|
||||
@@ -977,16 +960,17 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
if (result)
|
||||
break;
|
||||
|
||||
result = AddFormData(&form,
|
||||
"Content-Disposition: form-data; name=\"", 0, &size);
|
||||
result = AddFormDataf(&form, &size,
|
||||
"Content-Disposition: form-data; name=\"");
|
||||
if (result)
|
||||
break;
|
||||
|
||||
result = AddFormData(&form, post->name, post->namelength, &size);
|
||||
result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
|
||||
&size);
|
||||
if (result)
|
||||
break;
|
||||
|
||||
result = AddFormData(&form, "\"", 0, &size);
|
||||
result = AddFormDataf(&form, &size, "\"");
|
||||
if (result)
|
||||
break;
|
||||
|
||||
@@ -1071,7 +1055,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
}
|
||||
#endif
|
||||
|
||||
result = AddFormData(&form, "\r\n\r\n", 0, &size);
|
||||
result = AddFormDataf(&form, &size, "\r\n\r\n");
|
||||
if (result)
|
||||
break;
|
||||
|
||||
@@ -1079,11 +1063,10 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
(post->flags & HTTPPOST_READFILE)) {
|
||||
/* we should include the contents from the specified file */
|
||||
FILE *fileread;
|
||||
char buffer[1024];
|
||||
size_t nread;
|
||||
|
||||
fileread = strequal("-", file->contents)?
|
||||
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
|
||||
|
||||
/*
|
||||
* VMS: This only allows for stream files on VMS. Stream files are
|
||||
* OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
|
||||
@@ -1091,13 +1074,27 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
*/
|
||||
|
||||
if(fileread) {
|
||||
while((nread = fread(buffer, 1, 1024, fileread))) {
|
||||
result = AddFormData(&form, buffer, nread, &size);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
if(fileread != stdin)
|
||||
if(fileread != stdin) {
|
||||
/* close the file again */
|
||||
fclose(fileread);
|
||||
/* add the file name only - for later reading from this */
|
||||
result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
|
||||
}
|
||||
else {
|
||||
/* When uploading from stdin, we can't know the size of the file,
|
||||
* thus must read the full file as before. We *could* use chunked
|
||||
* transfer-encoding, but that only works for HTTP 1.1 and we
|
||||
* can't be sure we work with such a server.
|
||||
*/
|
||||
size_t nread;
|
||||
char buffer[512];
|
||||
while((nread = fread(buffer, 1, sizeof(buffer), fileread))) {
|
||||
result = AddFormData(&form, FORM_DATA, buffer, nread, &size);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
Curl_formclean(firstform);
|
||||
free(boundary);
|
||||
@@ -1115,16 +1112,16 @@ CURLcode Curl_getFormData(struct FormData **finalform,
|
||||
}
|
||||
else if (post->flags & HTTPPOST_BUFFER) {
|
||||
/* include contents of buffer */
|
||||
result = AddFormData(&form, post->buffer, post->bufferlength,
|
||||
&size);
|
||||
result = AddFormData(&form, FORM_DATA, post->buffer,
|
||||
post->bufferlength, &size);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
||||
else {
|
||||
/* include the contents we got */
|
||||
result = AddFormData(&form, post->contents, post->contentslength,
|
||||
&size);
|
||||
result = AddFormData(&form, FORM_DATA, post->contents,
|
||||
post->contentslength, &size);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
@@ -1183,10 +1180,32 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata )
|
||||
|
||||
form->data = formdata;
|
||||
form->sent = 0;
|
||||
form->fp = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t readfromfile(struct Form *form, char *buffer, size_t size)
|
||||
{
|
||||
size_t nread;
|
||||
if(!form->fp) {
|
||||
/* this file hasn't yet been opened */
|
||||
form->fp = fopen(form->data->line, "rb"); /* b is for binary */
|
||||
if(!form->fp)
|
||||
return -1; /* failure */
|
||||
}
|
||||
nread = fread(buffer, 1, size, form->fp);
|
||||
|
||||
if(nread != size) {
|
||||
/* this is the last chunk form the file, move on */
|
||||
fclose(form->fp);
|
||||
form->fp = NULL;
|
||||
form->data = form->data->next;
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_FormReader() is the fread() emulation function that will be used to
|
||||
* deliver the formdata to the transfer loop and then sent away to the peer.
|
||||
@@ -1207,6 +1226,9 @@ size_t Curl_FormReader(char *buffer,
|
||||
if(!form->data)
|
||||
return 0; /* nothing, error, empty */
|
||||
|
||||
if(form->data->type == FORM_FILE)
|
||||
return readfromfile(form, buffer, wantedsize);
|
||||
|
||||
do {
|
||||
|
||||
if( (form->data->length - form->sent ) > wantedsize - gotsize) {
|
||||
@@ -1228,7 +1250,7 @@ size_t Curl_FormReader(char *buffer,
|
||||
|
||||
form->data = form->data->next; /* advance */
|
||||
|
||||
} while(form->data);
|
||||
} while(form->data && (form->data->type == FORM_DATA));
|
||||
/* If we got an empty line and we have more data, we proceed to the next
|
||||
line immediately to avoid returning zero before we've reached the end.
|
||||
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
|
||||
@@ -1458,4 +1480,53 @@ int main(int argc, char **argv)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
#else /* CURL_DISABLE_HTTP */
|
||||
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
|
||||
struct curl_httppost **last_post,
|
||||
...)
|
||||
{
|
||||
(void)httppost;
|
||||
(void)last_post;
|
||||
return CURL_FORMADD_DISABLED;
|
||||
}
|
||||
|
||||
void curl_formfree(struct curl_httppost *form)
|
||||
{
|
||||
(void)form;
|
||||
/* does nothing HTTP is disabled */
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
/*
|
||||
* Curl_FormBoundary() creates a suitable boundary string and returns an
|
||||
* allocated one. This is also used by SSL-code so it must be present even
|
||||
* if HTTP is disabled!
|
||||
*/
|
||||
char *Curl_FormBoundary(void)
|
||||
{
|
||||
char *retstring;
|
||||
static int randomizer=0; /* this is just so that two boundaries within
|
||||
the same form won't be identical */
|
||||
size_t i;
|
||||
|
||||
static char table16[]="abcdef0123456789";
|
||||
|
||||
retstring = (char *)malloc(BOUNDARY_LENGTH+1);
|
||||
|
||||
if(!retstring)
|
||||
return NULL; /* failed */
|
||||
|
||||
srand(time(NULL)+randomizer++); /* seed */
|
||||
|
||||
strcpy(retstring, "----------------------------");
|
||||
|
||||
for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
|
||||
retstring[i] = table16[rand()%16];
|
||||
|
||||
/* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
|
||||
combinations */
|
||||
retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
|
||||
|
||||
return retstring;
|
||||
}
|
||||
|
@@ -23,17 +23,25 @@
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
enum formtype {
|
||||
FORM_DATA, /* regular data */
|
||||
FORM_FILE /* 'line' points to a file name we should read from */
|
||||
};
|
||||
|
||||
/* plain and simple linked list with lines to send */
|
||||
struct FormData {
|
||||
struct FormData *next;
|
||||
enum formtype type;
|
||||
char *line;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct Form {
|
||||
struct FormData *data; /* current form line to send */
|
||||
unsigned int sent; /* number of bytes of the current line that has already
|
||||
been sent in a previous invoke */
|
||||
size_t sent; /* number of bytes of the current line that has
|
||||
already been sent in a previous invoke */
|
||||
FILE *fp; /* file to read from */
|
||||
};
|
||||
|
||||
/* used by FormAdd for temporary storage */
|
||||
|
603
lib/ftp.c
603
lib/ftp.c
@@ -119,6 +119,10 @@ static CURLcode ftp_cwd(struct connectdata *conn, char *path);
|
||||
static CURLcode ftp_mkd(struct connectdata *conn, char *path);
|
||||
static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
|
||||
static CURLcode ftp_quit(struct connectdata *conn);
|
||||
static CURLcode ftp_3rdparty_pretransfer(struct connectdata *conn);
|
||||
static CURLcode ftp_3rdparty_transfer(struct connectdata *conn);
|
||||
static CURLcode ftp_regular_transfer(struct connectdata *conn);
|
||||
static CURLcode ftp_3rdparty(struct connectdata *conn);
|
||||
|
||||
/* easy-to-use macro: */
|
||||
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result
|
||||
@@ -369,7 +373,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
|
||||
/* output debug output if that is requested */
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline);
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline, conn->host.dispname);
|
||||
|
||||
/*
|
||||
* We pass all response-lines to the callback function registered
|
||||
@@ -487,6 +491,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
||||
ftp->passwd = conn->passwd;
|
||||
ftp->response_time = 3600; /* set default response time-out */
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if (conn->bits.tunnel_proxy) {
|
||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||
result = Curl_ConnectHTTPProxyTunnel(conn, FIRSTSOCKET,
|
||||
@@ -494,6 +499,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
if(conn->protocol & PROT_FTPS) {
|
||||
/* FTPS is simply ftp with SSL for the control channel */
|
||||
@@ -844,8 +850,13 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
ftp->no_transfer = FALSE;
|
||||
ftp->dont_check = FALSE;
|
||||
|
||||
if (!result && conn->sec_conn) { /* 3rd party transfer */
|
||||
/* "done" with the secondary connection */
|
||||
result = Curl_ftp_done(conn->sec_conn, status);
|
||||
}
|
||||
|
||||
/* Send any post-transfer QUOTE strings? */
|
||||
if(!result && data->set.postquote)
|
||||
if(!status && !result && data->set.postquote)
|
||||
result = ftp_sendquote(conn, data->set.postquote);
|
||||
|
||||
return result;
|
||||
@@ -1702,6 +1713,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
||||
/* this just dumps information about this second connection */
|
||||
ftp_pasv_verbose(conn, conninfo, newhostp, connectport);
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(conn->bits.tunnel_proxy) {
|
||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||
result = Curl_ConnectHTTPProxyTunnel(conn, SECONDARYSOCKET,
|
||||
@@ -1709,6 +1721,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -2334,11 +2347,393 @@ CURLcode ftp_perform(struct connectdata *conn,
|
||||
* parts etc as a wrapper to the actual DO function (ftp_perform).
|
||||
*
|
||||
* The input argument is already checked for validity.
|
||||
*/
|
||||
CURLcode Curl_ftp(struct connectdata *conn)
|
||||
{
|
||||
CURLcode retcode = CURLE_OK;
|
||||
|
||||
if (conn->sec_conn) /* 3rd party transfer */
|
||||
retcode = ftp_3rdparty(conn);
|
||||
else
|
||||
retcode = ftp_regular_transfer(conn);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Curl_ftpsendf()
|
||||
*
|
||||
* Sends the formated string as a ftp command to a ftp server
|
||||
*
|
||||
* NOTE: we build the command in a fixed-length buffer, which sets length
|
||||
* restrictions on the command!
|
||||
*/
|
||||
CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
ssize_t bytes_written;
|
||||
char s[256];
|
||||
size_t write_len;
|
||||
char *sptr=s;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(s, 250, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
strcat(s, "\r\n"); /* append a trailing CRLF */
|
||||
|
||||
bytes_written=0;
|
||||
write_len = strlen(s);
|
||||
|
||||
while(1) {
|
||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||
&bytes_written);
|
||||
|
||||
if(CURLE_OK != res)
|
||||
break;
|
||||
|
||||
if(conn->data->set.verbose)
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, bytes_written, conn->host.dispname);
|
||||
|
||||
if(bytes_written != (ssize_t)write_len) {
|
||||
write_len -= bytes_written;
|
||||
sptr += bytes_written;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_quit()
|
||||
*
|
||||
* This should be called before calling sclose() on an ftp control connection
|
||||
* (not data connections). We should then wait for the response from the
|
||||
* server before returning. The calling code should then try to close the
|
||||
* connection.
|
||||
*
|
||||
*/
|
||||
static CURLcode ftp_quit(struct connectdata *conn)
|
||||
{
|
||||
ssize_t nread;
|
||||
int ftpcode;
|
||||
CURLcode ret = CURLE_OK;
|
||||
|
||||
if(conn->proto.ftp->ctl_valid) {
|
||||
ret = Curl_ftpsendf(conn, "%s", "QUIT");
|
||||
if(CURLE_OK == ret)
|
||||
ret = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Curl_ftp_disconnect()
|
||||
*
|
||||
* Disconnect from an FTP server. Cleanup protocol-specific per-connection
|
||||
* resources
|
||||
*/
|
||||
CURLcode Curl_ftp_disconnect(struct connectdata *conn)
|
||||
{
|
||||
struct FTP *ftp= conn->proto.ftp;
|
||||
|
||||
/* We cannot send quit unconditionally. If this connection is stale or
|
||||
bad in any way, sending quit and waiting around here will make the
|
||||
disconnect wait in vain and cause more problems than we need to.
|
||||
|
||||
ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
|
||||
will try to send the QUIT command, otherwise it will just return.
|
||||
*/
|
||||
|
||||
/* The FTP session may or may not have been allocated/setup at this point! */
|
||||
if(ftp) {
|
||||
(void)ftp_quit(conn); /* ignore errors on the QUIT */
|
||||
|
||||
if(ftp->entrypath)
|
||||
free(ftp->entrypath);
|
||||
if(ftp->cache) {
|
||||
free(ftp->cache);
|
||||
ftp->cache = NULL;
|
||||
}
|
||||
freedirs(ftp);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_mkd()
|
||||
*
|
||||
* Makes a directory on the FTP server.
|
||||
*
|
||||
* Calls failf()
|
||||
*/
|
||||
static CURLcode ftp_mkd(struct connectdata *conn, char *path)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
int ftpcode; /* for ftp status */
|
||||
ssize_t nread;
|
||||
|
||||
/* Create a directory on the remote server */
|
||||
FTPSENDF(conn, "MKD %s", path);
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
switch(ftpcode) {
|
||||
case 257:
|
||||
/* success! */
|
||||
infof( conn->data , "Created remote directory %s\n" , path );
|
||||
break;
|
||||
case 550:
|
||||
failf(conn->data, "Permission denied to make directory %s", path);
|
||||
result = CURLE_FTP_ACCESS_DENIED;
|
||||
break;
|
||||
default:
|
||||
failf(conn->data, "unrecognized MKD response: %d", ftpcode );
|
||||
result = CURLE_FTP_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_cwd()
|
||||
*
|
||||
* Send 'CWD' to the remote server to Change Working Directory. It is the ftp
|
||||
* version of the unix 'cd' command. This function is only called from the
|
||||
* ftp_cwd_and_mkd() function these days.
|
||||
*
|
||||
* This function does NOT call failf().
|
||||
*/
|
||||
static
|
||||
CURLcode ftp_cwd(struct connectdata *conn, char *path)
|
||||
{
|
||||
ssize_t nread;
|
||||
int ftpcode;
|
||||
CURLcode result;
|
||||
|
||||
FTPSENDF(conn, "CWD %s", path);
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
if (!result) {
|
||||
/* According to RFC959, CWD is supposed to return 250 on success, but
|
||||
there seem to be non-compliant FTP servers out there that return 200,
|
||||
so we accept any '2xy' code here. */
|
||||
if (ftpcode/100 != 2)
|
||||
result = CURLE_FTP_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_cwd_and_mkd()
|
||||
*
|
||||
* Change to the given directory. If the directory is not present, and we
|
||||
* have been told to allow it, then create the directory and cd to it.
|
||||
*
|
||||
*/
|
||||
static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
result = ftp_cwd(conn, path);
|
||||
if (result) {
|
||||
if(conn->data->set.ftp_create_missing_dirs) {
|
||||
result = ftp_mkd(conn, path);
|
||||
if (result)
|
||||
/* ftp_mkd() calls failf() itself */
|
||||
return result;
|
||||
result = ftp_cwd(conn, path);
|
||||
}
|
||||
if(result)
|
||||
failf(conn->data, "Couldn't cd to %s", path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_3rdparty_pretransfer()
|
||||
*
|
||||
* Preparation for 3rd party transfer.
|
||||
*
|
||||
*/
|
||||
static CURLcode ftp_3rdparty_pretransfer(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct connectdata *sec_conn = conn->sec_conn;
|
||||
|
||||
/* sets transfer type */
|
||||
result = ftp_transfertype(conn, data->set.ftp_ascii);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = ftp_transfertype(sec_conn, data->set.ftp_ascii);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/* Send any PREQUOTE strings after transfer type is set? */
|
||||
if (data->set.source_prequote) {
|
||||
/* sends command(s) to source server before file transfer */
|
||||
result = ftp_sendquote(sec_conn, data->set.source_prequote);
|
||||
}
|
||||
if (!result && data->set.prequote)
|
||||
result = ftp_sendquote(conn, data->set.prequote);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_3rdparty_transfer()
|
||||
*
|
||||
* Performs 3rd party transfer.
|
||||
*
|
||||
*/
|
||||
static CURLcode ftp_3rdparty_transfer(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t nread;
|
||||
int ftpcode, ip[4], port[2];
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct connectdata *sec_conn = conn->sec_conn;
|
||||
char *buf = data->state.buffer; /* this is our buffer */
|
||||
char *str = buf;
|
||||
char pasv_port[50];
|
||||
const char *stor_cmd;
|
||||
struct connectdata *pasv_conn;
|
||||
struct connectdata *port_conn;
|
||||
|
||||
if (data->set.pasvHost == CURL_TARGET_PASV) {
|
||||
pasv_conn = conn;
|
||||
port_conn = sec_conn;
|
||||
}
|
||||
else {
|
||||
pasv_conn = sec_conn;
|
||||
port_conn = conn;
|
||||
}
|
||||
|
||||
/* sets the passive mode */
|
||||
FTPSENDF(pasv_conn, "%s", "PASV");
|
||||
result = Curl_GetFTPResponse(&nread, pasv_conn, &ftpcode);
|
||||
if (result) return result;
|
||||
if (ftpcode != 227) {
|
||||
failf(data, "Odd return code after PASV:%s", buf + 3);
|
||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||
}
|
||||
|
||||
while (*str) {
|
||||
if (6 == sscanf(str, "%d,%d,%d,%d,%d,%d",
|
||||
&ip[0], &ip[1], &ip[2], &ip[3], &port[0], &port[1]))
|
||||
break;
|
||||
str++;
|
||||
}
|
||||
|
||||
if (!*str) {
|
||||
failf(pasv_conn->data, "Couldn't interpret this 227-reply: %s", buf);
|
||||
return CURLE_FTP_WEIRD_227_FORMAT;
|
||||
}
|
||||
|
||||
snprintf(pasv_port, sizeof(pasv_port), "%d,%d,%d,%d,%d,%d", ip[0], ip[1],
|
||||
ip[2], ip[3], port[0], port[1]);
|
||||
|
||||
/* sets data connection between remote hosts */
|
||||
FTPSENDF(port_conn, "PORT %s", pasv_port);
|
||||
result = Curl_GetFTPResponse(&nread, port_conn, &ftpcode);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (ftpcode != 200) {
|
||||
failf(data, "PORT command attempts failed:%s", buf + 3);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
/* we might append onto the file instead of overwriting it */
|
||||
stor_cmd = data->set.ftp_append?"APPE":"STOR";
|
||||
|
||||
/* transfers file between remote hosts */
|
||||
FTPSENDF(sec_conn, "RETR %s", data->set.source_path);
|
||||
|
||||
if(data->set.pasvHost == CURL_TARGET_PASV) {
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, sec_conn, &ftpcode);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (ftpcode != 150) {
|
||||
failf(data, "Failed RETR: %s", buf + 4);
|
||||
return CURLE_FTP_COULDNT_RETR_FILE;
|
||||
}
|
||||
|
||||
result = Curl_ftpsendf(conn, "%s %s", stor_cmd, conn->path);
|
||||
if(CURLE_OK == result)
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (ftpcode != 150) {
|
||||
failf(data, "Failed FTP upload: %s", buf + 4);
|
||||
return CURLE_FTP_COULDNT_STOR_FILE;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
result = Curl_ftpsendf(conn, "%s %s", stor_cmd, conn->path);
|
||||
if(CURLE_OK == result)
|
||||
result = Curl_GetFTPResponse(&nread, sec_conn, &ftpcode);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (ftpcode != 150) {
|
||||
failf(data, "Failed FTP upload: %s", buf + 4);
|
||||
return CURLE_FTP_COULDNT_STOR_FILE;
|
||||
}
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (ftpcode != 150) {
|
||||
failf(data, "Failed FTP upload: %s", buf + 4);
|
||||
return CURLE_FTP_COULDNT_STOR_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_regular_transfer()
|
||||
*
|
||||
* The input argument is already checked for validity.
|
||||
* Performs a regular transfer between local and remote hosts.
|
||||
*
|
||||
* ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
|
||||
* Curl_ftp_done() function without finding any major problem.
|
||||
*/
|
||||
CURLcode Curl_ftp(struct connectdata *conn)
|
||||
static
|
||||
CURLcode ftp_regular_transfer(struct connectdata *conn)
|
||||
{
|
||||
CURLcode retcode=CURLE_OK;
|
||||
bool connected=0;
|
||||
@@ -2448,207 +2843,27 @@ CURLcode Curl_ftp(struct connectdata *conn)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Curl_ftpsendf()
|
||||
*
|
||||
* Sends the formated string as a ftp command to a ftp server
|
||||
*
|
||||
* NOTE: we build the command in a fixed-length buffer, which sets length
|
||||
* restrictions on the command!
|
||||
*/
|
||||
CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
ssize_t bytes_written;
|
||||
char s[256];
|
||||
size_t write_len;
|
||||
char *sptr=s;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(s, 250, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
strcat(s, "\r\n"); /* append a trailing CRLF */
|
||||
|
||||
bytes_written=0;
|
||||
write_len = strlen(s);
|
||||
|
||||
while(1) {
|
||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||
&bytes_written);
|
||||
|
||||
if(CURLE_OK != res)
|
||||
break;
|
||||
|
||||
if(conn->data->set.verbose)
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, bytes_written);
|
||||
|
||||
if(bytes_written != (ssize_t)write_len) {
|
||||
write_len -= bytes_written;
|
||||
sptr += bytes_written;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_quit()
|
||||
*
|
||||
* This should be called before calling sclose() on an ftp control connection
|
||||
* (not data connections). We should then wait for the response from the
|
||||
* server before returning. The calling code should then try to close the
|
||||
* connection.
|
||||
* ftp_3rdparty()
|
||||
*
|
||||
* The input argument is already checked for validity.
|
||||
* Performs a 3rd party transfer between two remote hosts.
|
||||
*/
|
||||
static CURLcode ftp_quit(struct connectdata *conn)
|
||||
static CURLcode ftp_3rdparty(struct connectdata *conn)
|
||||
{
|
||||
ssize_t nread;
|
||||
int ftpcode;
|
||||
CURLcode ret = CURLE_OK;
|
||||
CURLcode retcode = CURLE_OK;
|
||||
|
||||
if(conn->proto.ftp->ctl_valid) {
|
||||
ret = Curl_ftpsendf(conn, "%s", "QUIT");
|
||||
if(CURLE_OK == ret)
|
||||
ret = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
}
|
||||
conn->proto.ftp->ctl_valid = conn->sec_conn->proto.ftp->ctl_valid = TRUE;
|
||||
conn->size = conn->sec_conn->size = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
retcode = ftp_3rdparty_pretransfer(conn);
|
||||
if (!retcode)
|
||||
retcode = ftp_3rdparty_transfer(conn);
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Curl_ftp_disconnect()
|
||||
*
|
||||
* Disconnect from an FTP server. Cleanup protocol-specific per-connection
|
||||
* resources
|
||||
*/
|
||||
CURLcode Curl_ftp_disconnect(struct connectdata *conn)
|
||||
{
|
||||
struct FTP *ftp= conn->proto.ftp;
|
||||
|
||||
/* We cannot send quit unconditionally. If this connection is stale or
|
||||
bad in any way, sending quit and waiting around here will make the
|
||||
disconnect wait in vain and cause more problems than we need to.
|
||||
|
||||
ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
|
||||
will try to send the QUIT command, otherwise it will just return.
|
||||
*/
|
||||
|
||||
/* The FTP session may or may not have been allocated/setup at this point! */
|
||||
if(ftp) {
|
||||
(void)ftp_quit(conn); /* ignore errors on the QUIT */
|
||||
|
||||
if(ftp->entrypath)
|
||||
free(ftp->entrypath);
|
||||
if(ftp->cache) {
|
||||
free(ftp->cache);
|
||||
ftp->cache = NULL;
|
||||
}
|
||||
freedirs(ftp);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_mkd()
|
||||
*
|
||||
* Makes a directory on the FTP server.
|
||||
*
|
||||
* Calls failf()
|
||||
*/
|
||||
CURLcode ftp_mkd(struct connectdata *conn, char *path)
|
||||
{
|
||||
CURLcode result=CURLE_OK;
|
||||
int ftpcode; /* for ftp status */
|
||||
ssize_t nread;
|
||||
|
||||
/* Create a directory on the remote server */
|
||||
FTPSENDF(conn, "MKD %s", path);
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
switch(ftpcode) {
|
||||
case 257:
|
||||
/* success! */
|
||||
infof( conn->data , "Created remote directory %s\n" , path );
|
||||
break;
|
||||
case 550:
|
||||
failf(conn->data, "Permission denied to make directory %s", path);
|
||||
result = CURLE_FTP_ACCESS_DENIED;
|
||||
break;
|
||||
default:
|
||||
failf(conn->data, "unrecognized MKD response: %d", ftpcode );
|
||||
result = CURLE_FTP_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_cwd()
|
||||
*
|
||||
* Send 'CWD' to the remote server to Change Working Directory. It is the ftp
|
||||
* version of the unix 'cd' command. This function is only called from the
|
||||
* ftp_cwd_and_mkd() function these days.
|
||||
*
|
||||
* This function does NOT call failf().
|
||||
*/
|
||||
static
|
||||
CURLcode ftp_cwd(struct connectdata *conn, char *path)
|
||||
{
|
||||
ssize_t nread;
|
||||
int ftpcode;
|
||||
CURLcode result;
|
||||
|
||||
FTPSENDF(conn, "CWD %s", path);
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
if (!result) {
|
||||
/* According to RFC959, CWD is supposed to return 250 on success, but
|
||||
there seem to be non-compliant FTP servers out there that return 200,
|
||||
so we accept any '2xy' code here. */
|
||||
if (ftpcode/100 != 2)
|
||||
result = CURLE_FTP_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* ftp_cwd_and_mkd()
|
||||
*
|
||||
* Change to the given directory. If the directory is not present, and we
|
||||
* have been told to allow it, then create the directory and cd to it.
|
||||
*
|
||||
*/
|
||||
static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
result = ftp_cwd(conn, path);
|
||||
if (result) {
|
||||
if(conn->data->set.ftp_create_missing_dirs) {
|
||||
result = ftp_mkd(conn, path);
|
||||
if (result)
|
||||
/* ftp_mkd() calls failf() itself */
|
||||
return result;
|
||||
result = ftp_cwd(conn, path);
|
||||
}
|
||||
if(result)
|
||||
failf(conn->data, "Couldn't cd to %s", path);
|
||||
}
|
||||
return result;
|
||||
return retcode;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_FTP */
|
||||
|
@@ -1758,7 +1758,8 @@ ToHour (Hours, Meridian)
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
/* NOTREACHED */
|
||||
/* NOTREACHED - but make gcc happy! */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@@ -26,6 +26,11 @@
|
||||
#define YYDEBUG 0
|
||||
#endif
|
||||
|
||||
#ifndef YYSTACK_USE_ALLOCA
|
||||
/* to satisfy gcc -Wundef, we set this to 0 */
|
||||
#define YYSTACK_USE_ALLOCA 0
|
||||
#endif
|
||||
|
||||
/* Since the code of getdate.y is not included in the Emacs executable
|
||||
itself, there is no need to #define static in this file. Even if
|
||||
the code were included in the Emacs executable, it probably
|
||||
@@ -717,9 +722,10 @@ ToHour (int Hours, MERIDIAN Meridian)
|
||||
Hours = 0;
|
||||
return Hours + 12;
|
||||
default:
|
||||
abort ();
|
||||
break; /* used to do abort() here */
|
||||
}
|
||||
/* NOTREACHED */
|
||||
/* NOTREACHED - but make gcc happy! */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1073,31 +1079,3 @@ curl_getdate (const char *p, const time_t *now)
|
||||
|
||||
return Start;
|
||||
}
|
||||
|
||||
#if defined (TEST)
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
main (int ac, char *av[])
|
||||
{
|
||||
char buff[MAX_BUFF_LEN + 1];
|
||||
time_t d;
|
||||
|
||||
(void) printf ("Enter date, or blank line to exit.\n\t> ");
|
||||
(void) fflush (stdout);
|
||||
|
||||
buff[MAX_BUFF_LEN] = 0;
|
||||
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
|
||||
{
|
||||
d = curl_getdate (buff, (time_t *) NULL);
|
||||
if (d == -1)
|
||||
(void) printf ("Bad format - couldn't convert.\n");
|
||||
else
|
||||
(void) printf ("%s", ctime (&d));
|
||||
(void) printf ("\t> ");
|
||||
(void) fflush (stdout);
|
||||
}
|
||||
exit (0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif /* defined (TEST) */
|
||||
|
38
lib/hostip.c
38
lib/hostip.c
@@ -79,6 +79,7 @@
|
||||
#include "share.h"
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "inet_ntop.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -167,6 +168,43 @@ void Curl_global_host_cache_dtor(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return # of adresses in a Curl_addrinfo struct
|
||||
*/
|
||||
int Curl_num_addresses(const Curl_addrinfo *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
for (i = 0; addr; addr = addr->ai_next, i++)
|
||||
#else
|
||||
for (i = 0; addr->h_addr_list[i]; i++)
|
||||
#endif
|
||||
;
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_printable_address() returns a printable version of the 1st address
|
||||
* given in the 'ip' argument. The result will be stored in the buf that is
|
||||
* bufsize bytes big.
|
||||
*
|
||||
* If the conversion fails, it returns NULL.
|
||||
*/
|
||||
const char *Curl_printable_address(const Curl_ipconnect *ip,
|
||||
char *buf, size_t bufsize)
|
||||
{
|
||||
#ifdef CURLRES_IPV6
|
||||
const void *ip4 = &((const struct sockaddr_in*)ip->ai_addr)->sin_addr;
|
||||
const void *ip6 = &((const struct sockaddr_in6*)ip->ai_addr)->sin6_addr;
|
||||
int af = ip->ai_family;
|
||||
|
||||
return Curl_inet_ntop(af, af == AF_INET6 ? ip6 : ip4, buf, bufsize);
|
||||
#else
|
||||
return Curl_inet_ntop(AF_INET, ip, buf, bufsize);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of characters that an integer would use in a string
|
||||
* (base 10).
|
||||
|
12
lib/hostip.h
12
lib/hostip.h
@@ -102,6 +102,9 @@ curl_hash *Curl_mk_dnscache(void);
|
||||
/* prune old entries from the DNS cache */
|
||||
void Curl_hostcache_prune(struct SessionHandle *data);
|
||||
|
||||
/* Return # of adresses in a Curl_addrinfo struct */
|
||||
int Curl_num_addresses (const Curl_addrinfo *addr);
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
void curl_dofreeaddrinfo(struct addrinfo *freethis,
|
||||
int line, const char *source);
|
||||
@@ -133,12 +136,11 @@ void Curl_hostent_relocate(struct hostent *h, long offset);
|
||||
Curl_addrinfo *Curl_addrinfo_copy(Curl_addrinfo *orig);
|
||||
|
||||
/*
|
||||
* (IPv6) Curl_printable_address() returns a printable version of the
|
||||
* ai->ai_addr address given in the 2nd argument. The first should be the
|
||||
* ai->ai_family and the result will be stored in the buf that is bufsize
|
||||
* bytes big.
|
||||
* Curl_printable_address() returns a printable version of the 1st address
|
||||
* given in the 'ip' argument. The result will be stored in the buf that is
|
||||
* bufsize bytes big.
|
||||
*/
|
||||
const char *Curl_printable_address(int af, void *addr,
|
||||
const char *Curl_printable_address(const Curl_ipconnect *ip,
|
||||
char *buf, size_t bufsize);
|
||||
|
||||
/*
|
||||
|
@@ -79,7 +79,6 @@
|
||||
#include "share.h"
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "inet_ntop.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -106,26 +105,6 @@ void Curl_freeaddrinfo(Curl_addrinfo *p)
|
||||
freeaddrinfo(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_printable_address() returns a printable version of the ai->ai_addr
|
||||
* address given in the 2nd argument. The first should be the ai->ai_family
|
||||
* and the result will be stored in the buf that is bufsize bytes big.
|
||||
*
|
||||
* If the conversion fails, it returns NULL.
|
||||
*/
|
||||
const char *Curl_printable_address(int af, void *addr,
|
||||
char *buf, size_t bufsize)
|
||||
{
|
||||
const struct in_addr *addr4 =
|
||||
&((const struct sockaddr_in*)addr)->sin_addr;
|
||||
const struct in6_addr *addr6 =
|
||||
&((const struct sockaddr_in6*)addr)->sin6_addr;
|
||||
return Curl_inet_ntop(af, af == AF_INET6 ?
|
||||
(const void *)addr6 :
|
||||
(const void *)addr4, buf, bufsize);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CURLRES_ASYNCH
|
||||
/*
|
||||
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
|
||||
|
@@ -142,7 +142,7 @@ static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai)
|
||||
|
||||
trace_it(" fam %2d, CNAME %s, ",
|
||||
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
|
||||
if (Curl_printable_address(ai->ai_family, ai->ai_addr, buf, sizeof(buf)))
|
||||
if (Curl_printable_address(ai, buf, sizeof(buf)))
|
||||
trace_it("%s\n", buf);
|
||||
else
|
||||
trace_it("failed; %s\n", Curl_strerror(conn,WSAGetLastError()));
|
||||
|
97
lib/http.c
97
lib/http.c
@@ -168,29 +168,25 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy)
|
||||
static bool pickoneauth(struct auth *pick)
|
||||
{
|
||||
bool picked;
|
||||
if(pick->avail) {
|
||||
/* only deal with authentication we want */
|
||||
long avail = pick->avail & pick->want;
|
||||
picked = TRUE;
|
||||
/* only deal with authentication we want */
|
||||
long avail = pick->avail & pick->want;
|
||||
picked = TRUE;
|
||||
|
||||
/* The order of these checks is highly relevant, as this will be the order
|
||||
of preference in case of the existance of multiple accepted types. */
|
||||
if(avail & CURLAUTH_GSSNEGOTIATE)
|
||||
pick->picked = CURLAUTH_GSSNEGOTIATE;
|
||||
else if(avail & CURLAUTH_DIGEST)
|
||||
pick->picked = CURLAUTH_DIGEST;
|
||||
else if(avail & CURLAUTH_NTLM)
|
||||
pick->picked = CURLAUTH_NTLM;
|
||||
else if(avail & CURLAUTH_BASIC)
|
||||
pick->picked = CURLAUTH_BASIC;
|
||||
else {
|
||||
pick->picked = CURLAUTH_NONE; /* none was picked clear it */
|
||||
picked = FALSE;
|
||||
}
|
||||
pick->avail = CURLAUTH_NONE; /* clear it here */
|
||||
/* The order of these checks is highly relevant, as this will be the order
|
||||
of preference in case of the existance of multiple accepted types. */
|
||||
if(avail & CURLAUTH_GSSNEGOTIATE)
|
||||
pick->picked = CURLAUTH_GSSNEGOTIATE;
|
||||
else if(avail & CURLAUTH_DIGEST)
|
||||
pick->picked = CURLAUTH_DIGEST;
|
||||
else if(avail & CURLAUTH_NTLM)
|
||||
pick->picked = CURLAUTH_NTLM;
|
||||
else if(avail & CURLAUTH_BASIC)
|
||||
pick->picked = CURLAUTH_BASIC;
|
||||
else {
|
||||
pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
|
||||
picked = FALSE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
pick->avail = CURLAUTH_NONE; /* clear it here */
|
||||
|
||||
return picked;
|
||||
}
|
||||
@@ -212,22 +208,27 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
|
||||
if(data->state.authproblem)
|
||||
return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
|
||||
|
||||
if(conn->bits.user_passwd) {
|
||||
if(conn->bits.user_passwd &&
|
||||
((conn->keep.httpcode == 401) ||
|
||||
(conn->bits.authprobe && conn->keep.httpcode < 300))) {
|
||||
pickhost = pickoneauth(&data->state.authhost);
|
||||
if(!pickhost && (conn->keep.httpcode == 401))
|
||||
if(!pickhost)
|
||||
data->state.authproblem = TRUE;
|
||||
}
|
||||
if(conn->bits.proxy_user_passwd) {
|
||||
if(conn->bits.proxy_user_passwd &&
|
||||
((conn->keep.httpcode == 407) ||
|
||||
(conn->bits.authprobe && conn->keep.httpcode < 300))) {
|
||||
pickproxy = pickoneauth(&data->state.authproxy);
|
||||
if(!pickproxy && (conn->keep.httpcode == 407))
|
||||
if(!pickproxy)
|
||||
data->state.authproblem = TRUE;
|
||||
}
|
||||
|
||||
if(pickhost || pickproxy)
|
||||
conn->newurl = strdup(data->change.url); /* clone URL */
|
||||
|
||||
else if((data->info.httpcode < 400) &&
|
||||
(!data->state.authhost.done)) {
|
||||
else if((conn->keep.httpcode < 300) &&
|
||||
(!data->state.authhost.done) &&
|
||||
conn->bits.authprobe) {
|
||||
/* no (known) authentication available,
|
||||
authentication is not "done" yet and
|
||||
no authentication seems to be required and
|
||||
@@ -283,21 +284,17 @@ Curl_http_output_auth(struct connectdata *conn,
|
||||
return CURLE_OK; /* no authentication with no user or password */
|
||||
}
|
||||
|
||||
if(data->state.authhost.want &&
|
||||
!data->state.authhost.picked) {
|
||||
if(data->state.authhost.want && !data->state.authhost.picked)
|
||||
/* The app has selected one or more methods, but none has been picked
|
||||
so far by a server round-trip. Then we set the picked one to the
|
||||
want one, and if this is one single bit it'll be used instantly. */
|
||||
data->state.authhost.picked = data->state.authhost.want;
|
||||
}
|
||||
|
||||
if(data->state.authproxy.want &&
|
||||
!data->state.authproxy.picked) {
|
||||
/* The app has selected one or more methods, but none has been picked
|
||||
so far by a server round-trip. Then we set the picked one to the
|
||||
want one, and if this is one single bit it'll be used instantly. */
|
||||
if(data->state.authproxy.want && !data->state.authproxy.picked)
|
||||
/* The app has selected one or more methods, but none has been picked so
|
||||
far by a proxy round-trip. Then we set the picked one to the want one,
|
||||
and if this is one single bit it'll be used instantly. */
|
||||
data->state.authproxy.picked = data->state.authproxy.want;
|
||||
}
|
||||
|
||||
/* To prevent the user+password to get sent to other than the original
|
||||
host due to a location-follow, we do some weirdo checks here */
|
||||
@@ -740,7 +737,8 @@ CURLcode add_buffer_send(send_buffer *in,
|
||||
|
||||
if(conn->data->set.verbose)
|
||||
/* this data _may_ contain binary stuff */
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount);
|
||||
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount,
|
||||
conn->host.dispname);
|
||||
|
||||
*bytes_written += amount;
|
||||
|
||||
@@ -1044,7 +1042,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
||||
|
||||
/* output debug output if that is requested */
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline);
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline,
|
||||
conn->host.dispname);
|
||||
|
||||
/* send the header to the callback */
|
||||
writetype = CLIENTWRITE_HEADER;
|
||||
@@ -1080,7 +1079,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
||||
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
|
||||
&subversion,
|
||||
&k->httpcode)) {
|
||||
/* store the HTTP code */
|
||||
/* store the HTTP code from the proxy */
|
||||
data->info.httpproxycode = k->httpcode;
|
||||
}
|
||||
/* put back the letter we blanked out before */
|
||||
@@ -1098,9 +1097,10 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
||||
if(error)
|
||||
return CURLE_RECV_ERROR;
|
||||
|
||||
/* Deal with the possibly already received authenticate headers. 'newurl'
|
||||
is set to a new URL if we must loop. */
|
||||
Curl_http_auth_act(conn);
|
||||
if(data->info.httpproxycode != 200)
|
||||
/* Deal with the possibly already received authenticate
|
||||
headers. 'newurl' is set to a new URL if we must loop. */
|
||||
Curl_http_auth_act(conn);
|
||||
|
||||
} while(conn->newurl);
|
||||
|
||||
@@ -1277,14 +1277,13 @@ CURLcode Curl_http(struct connectdata *conn)
|
||||
case HTTPREQ_PUT:
|
||||
request = (char *)"PUT";
|
||||
break;
|
||||
default: /* this should never happen */
|
||||
case HTTPREQ_GET:
|
||||
request = (char *)"GET";
|
||||
break;
|
||||
case HTTPREQ_HEAD:
|
||||
request = (char *)"HEAD";
|
||||
break;
|
||||
default: /* this should never happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1312,7 +1311,11 @@ CURLcode Curl_http(struct connectdata *conn)
|
||||
httpreq = HTTPREQ_HEAD;
|
||||
request = (char *)"HEAD";
|
||||
conn->bits.no_body = TRUE;
|
||||
conn->bits.authprobe = TRUE; /* this is a request done to probe for
|
||||
authentication methods */
|
||||
}
|
||||
else
|
||||
conn->bits.authprobe = FALSE;
|
||||
|
||||
Curl_safefree(conn->allocptr.ref);
|
||||
if(data->change.referer && !checkheaders(data, "Referer:"))
|
||||
@@ -1764,13 +1767,11 @@ CURLcode Curl_http(struct connectdata *conn)
|
||||
}
|
||||
|
||||
if(!checkheaders(data, "Content-Type:")) {
|
||||
/* Get Content-Type: line from Curl_formpostheader, which happens
|
||||
to always be the first line. We can know this for sure since
|
||||
we always build the formpost linked list the same way!
|
||||
/* Get Content-Type: line from Curl_formpostheader.
|
||||
|
||||
The Content-Type header line also contains the MIME boundary
|
||||
string etc why disabling this header is likely to not make things
|
||||
work, but we support it anyway.
|
||||
work, but we support disabling it anyway.
|
||||
*/
|
||||
char *contentType;
|
||||
size_t linelength=0;
|
||||
|
@@ -50,5 +50,12 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
CURLcode Curl_http_auth_act(struct connectdata *conn);
|
||||
|
||||
int Curl_http_should_fail(struct connectdata *conn);
|
||||
|
||||
/* If only the PICKNONE bit is set, there has been a round-trip and we
|
||||
selected to use no auth at all. Ie, we actively select no auth, as opposed
|
||||
to not having one selected. The other CURLAUTH_* defines are present in the
|
||||
public curl/curl.h header. */
|
||||
#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -221,23 +221,37 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
char *cnonce;
|
||||
char *tmp = NULL;
|
||||
struct timeval now;
|
||||
|
||||
char **allocuserpwd;
|
||||
char *userp;
|
||||
char *passwdp;
|
||||
struct auth *authp;
|
||||
char **userp;
|
||||
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct digestdata *d;
|
||||
|
||||
if(proxy) {
|
||||
d = &data->state.proxydigest;
|
||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||
userp = conn->proxyuser;
|
||||
passwdp = conn->proxypasswd;
|
||||
authp = &data->state.authproxy;
|
||||
userp = &conn->allocptr.proxyuserpwd;
|
||||
}
|
||||
else {
|
||||
d = &data->state.digest;
|
||||
allocuserpwd = &conn->allocptr.userpwd;
|
||||
userp = conn->user;
|
||||
passwdp = conn->passwd;
|
||||
authp = &data->state.authhost;
|
||||
userp = &conn->allocptr.userpwd;
|
||||
}
|
||||
|
||||
/* not set means empty */
|
||||
if(!userp)
|
||||
userp=(char *)"";
|
||||
|
||||
if(!passwdp)
|
||||
passwdp=(char *)"";
|
||||
|
||||
if(!d->nonce) {
|
||||
authp->done = FALSE;
|
||||
return CURLE_OK;
|
||||
@@ -269,7 +283,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
*/
|
||||
|
||||
md5this = (unsigned char *)
|
||||
aprintf("%s:%s:%s", conn->user, d->realm, conn->passwd);
|
||||
aprintf("%s:%s:%s", userp, d->realm, passwdp);
|
||||
if(!md5this)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_md5it(md5buf, md5this);
|
||||
@@ -347,10 +361,10 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
|
||||
*/
|
||||
|
||||
Curl_safefree(conn->allocptr.userpwd);
|
||||
Curl_safefree(*allocuserpwd);
|
||||
|
||||
if (d->qop) {
|
||||
*userp =
|
||||
*allocuserpwd =
|
||||
aprintf( "%sAuthorization: Digest "
|
||||
"username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
@@ -361,7 +375,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
"qop=\"%s\", "
|
||||
"response=\"%s\"",
|
||||
proxy?"Proxy-":"",
|
||||
conn->user,
|
||||
userp,
|
||||
d->realm,
|
||||
d->nonce,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
@@ -376,7 +390,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
same nonce in the qop=auth mode. */
|
||||
}
|
||||
else {
|
||||
*userp =
|
||||
*allocuserpwd =
|
||||
aprintf( "%sAuthorization: Digest "
|
||||
"username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
@@ -384,40 +398,40 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
"uri=\"%s\", "
|
||||
"response=\"%s\"",
|
||||
proxy?"Proxy-":"",
|
||||
conn->user,
|
||||
userp,
|
||||
d->realm,
|
||||
d->nonce,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
request_digest);
|
||||
}
|
||||
if(!*userp)
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Add optional fields */
|
||||
if(d->opaque) {
|
||||
/* append opaque */
|
||||
tmp = aprintf("%s, opaque=\"%s\"", *userp, d->opaque);
|
||||
tmp = aprintf("%s, opaque=\"%s\"", *allocuserpwd, d->opaque);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
free(*userp);
|
||||
*userp = tmp;
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = tmp;
|
||||
}
|
||||
|
||||
if(d->algorithm) {
|
||||
/* append algorithm */
|
||||
tmp = aprintf("%s, algorithm=\"%s\"", *userp, d->algorithm);
|
||||
tmp = aprintf("%s, algorithm=\"%s\"", *allocuserpwd, d->algorithm);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
free(*userp);
|
||||
*userp = tmp;
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = tmp;
|
||||
}
|
||||
|
||||
/* append CRLF to the userpwd header */
|
||||
tmp = (char*) realloc(*userp, strlen(*userp) + 3 + 1);
|
||||
tmp = (char*) realloc(*allocuserpwd, strlen(*allocuserpwd) + 3 + 1);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
strcat(tmp, "\r\n");
|
||||
*userp = tmp;
|
||||
*allocuserpwd = tmp;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
@@ -427,12 +427,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
|
||||
if (user) {
|
||||
domain = userp;
|
||||
domlen = user - domain;
|
||||
domlen = (int)(user - domain);
|
||||
user++;
|
||||
}
|
||||
else
|
||||
user = userp;
|
||||
userlen = strlen(user);
|
||||
userlen = (int)strlen(user);
|
||||
|
||||
mkhash(passwdp, &ntlm->nonce[0], lmresp
|
||||
#ifdef USE_NTRESPONSES
|
||||
|
@@ -9,7 +9,6 @@
|
||||
curl_easy_setopt,
|
||||
curl_escape,
|
||||
curl_unescape,
|
||||
curl_formparse,
|
||||
curl_formfree,
|
||||
curl_getdate,
|
||||
curl_getenv,
|
||||
@@ -39,6 +38,8 @@
|
||||
curl_version_info,
|
||||
curl_share_init,
|
||||
curl_share_setopt,
|
||||
curl_share_cleanup
|
||||
|
||||
|
||||
curl_share_cleanup,
|
||||
curl_global_init_mem,
|
||||
curl_easy_strerror,
|
||||
curl_multi_strerror,
|
||||
curl_share_strerror
|
||||
|
@@ -30,7 +30,7 @@ BEGIN
|
||||
VALUE "OriginalFilename", "libcurl.dll\0"
|
||||
VALUE "ProductName", "The cURL library\0"
|
||||
VALUE "ProductVersion", LIBCURL_VERSION "\0"
|
||||
VALUE "LegalCopyright", "Copyright 1996-2003 by Daniel Stenberg. http://curl.haxx.se/docs/copyright.html\0"
|
||||
VALUE "LegalCopyright", "Copyright 1996-2004 by Daniel Stenberg. http://curl.haxx.se/docs/copyright.html\0"
|
||||
END
|
||||
END
|
||||
|
||||
|
44
lib/sendf.c
44
lib/sendf.c
@@ -142,7 +142,7 @@ void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(print_buffer, 1024, fmt, ap);
|
||||
va_end(ap);
|
||||
Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer));
|
||||
Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
|
||||
data->set.errorbuffer[len] = '\n';
|
||||
data->set.errorbuffer[++len] = '\0';
|
||||
}
|
||||
Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len);
|
||||
Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len, NULL);
|
||||
if(doneit)
|
||||
/* cut off the newline again */
|
||||
data->set.errorbuffer[--len]=0;
|
||||
@@ -204,7 +204,8 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
|
||||
break;
|
||||
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written);
|
||||
Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written,
|
||||
conn->host.dispname);
|
||||
|
||||
if((size_t)bytes_written != write_len) {
|
||||
/* if not all was written at once, we must advance the pointer, decrease
|
||||
@@ -440,11 +441,11 @@ int Curl_read(struct connectdata *conn, /* connection data */
|
||||
}
|
||||
|
||||
/* return 0 on success */
|
||||
int Curl_debug(struct SessionHandle *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
static int showit(struct SessionHandle *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
{
|
||||
static const char * const s_infotype[CURLINFO_END] = {
|
||||
"* ", "< ", "> ", "{ ", "} " };
|
||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||
|
||||
if(data->set.fdebug)
|
||||
return (*data->set.fdebug)(data, type, ptr, size,
|
||||
@@ -462,3 +463,34 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Curl_debug(struct SessionHandle *data, curl_infotype type,
|
||||
char *ptr, size_t size, char *host)
|
||||
{
|
||||
int rc;
|
||||
if(data->set.printhost && host) {
|
||||
char buffer[160];
|
||||
const char *t=NULL;
|
||||
switch (type) {
|
||||
case CURLINFO_HEADER_IN:
|
||||
case CURLINFO_DATA_IN:
|
||||
t = "from";
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
case CURLINFO_DATA_OUT:
|
||||
t = "to";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(t) {
|
||||
snprintf(buffer, sizeof(buffer), "[Data %s %s]", t, host);
|
||||
rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
|
||||
if(rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
rc = showit(data, type, ptr, size);
|
||||
return rc;
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ CURLcode Curl_write(struct connectdata *conn,
|
||||
|
||||
/* the function used to output verbose information */
|
||||
int Curl_debug(struct SessionHandle *handle, curl_infotype type,
|
||||
char *data, size_t size);
|
||||
char *data, size_t size, char *host);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -261,7 +261,8 @@ typedef int curl_socket_t;
|
||||
#error "ares does not yet support IPv6. Disable IPv6 or ares and rebuild"
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(USE_ARES)
|
||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(USE_ARES) && \
|
||||
!defined(__LCC__) /* lcc-win32 doesn't have _beginthreadex() */
|
||||
#ifdef ENABLE_IPV6
|
||||
#define USE_THREADING_GETADDRINFO
|
||||
#else
|
||||
@@ -304,7 +305,7 @@ typedef struct in_addr Curl_ipconnect;
|
||||
/* This could benefit from additional checks that some of the used/important
|
||||
header files are present as well before we define the USE_* define. */
|
||||
#define USE_LIBIDN
|
||||
#define LIBIDN_REQUIRED_VERSION "0.4.5"
|
||||
#define LIBIDN_REQUIRED_VERSION "0.4.1"
|
||||
#endif
|
||||
|
||||
#endif /* __CONFIG_H */
|
||||
|
@@ -77,6 +77,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
case CURL_LOCK_DATA_COOKIE:
|
||||
if (!share->cookies) {
|
||||
share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE );
|
||||
@@ -84,6 +85,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
||||
return CURLSHE_NOMEM;
|
||||
}
|
||||
break;
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */
|
||||
case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
|
||||
@@ -106,12 +108,14 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
case CURL_LOCK_DATA_COOKIE:
|
||||
if (share->cookies) {
|
||||
Curl_cookie_cleanup(share->cookies);
|
||||
share->cookies = NULL;
|
||||
}
|
||||
break;
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
case CURL_LOCK_DATA_SSL_SESSION:
|
||||
break;
|
||||
@@ -165,8 +169,10 @@ curl_share_cleanup(CURLSH *sh)
|
||||
if(share->hostcache)
|
||||
Curl_hash_destroy(share->hostcache);
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(share->cookies)
|
||||
Curl_cookie_cleanup(share->cookies);
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
|
||||
free (share);
|
||||
|
291
lib/ssluse.c
291
lib/ssluse.c
@@ -45,6 +45,10 @@
|
||||
#include "inet_pton.h"
|
||||
#include "ssluse.h"
|
||||
#include "connect.h" /* Curl_ourerrno() proto */
|
||||
#include "strequal.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
#include <openssl/rand.h>
|
||||
@@ -55,6 +59,10 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x0090581fL
|
||||
#define HAVE_SSL_GET1_SESSION 1
|
||||
#else
|
||||
@@ -731,40 +739,59 @@ static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
|
||||
|
||||
/* ====================================================== */
|
||||
#ifdef USE_SSLEAY
|
||||
static int
|
||||
cert_hostcheck(const char *certname, const char *hostname)
|
||||
{
|
||||
char *tmp;
|
||||
const char *certdomain;
|
||||
|
||||
if(!certname ||
|
||||
strlen(certname)<3 ||
|
||||
!hostname ||
|
||||
!strlen(hostname)) /* sanity check */
|
||||
/*
|
||||
* Match a hostname against a wildcard pattern.
|
||||
* E.g.
|
||||
* "foo.host.com" matches "*.host.com".
|
||||
*
|
||||
* We are a bit more liberal than RFC2818 describes in that we
|
||||
* accept multiple "*" in pattern (similar to what some other browsers do).
|
||||
* E.g.
|
||||
* "abc.def.domain.com" should strickly not match "*.domain.com", but we
|
||||
* don't consider "." to be important in CERT checking.
|
||||
*/
|
||||
#define HOST_NOMATCH 0
|
||||
#define HOST_MATCH 1
|
||||
|
||||
static int hostmatch(const char *hostname, const char *pattern)
|
||||
{
|
||||
while (1) {
|
||||
int c = *pattern++;
|
||||
|
||||
if (c == '\0')
|
||||
return (*hostname ? HOST_NOMATCH : HOST_MATCH);
|
||||
|
||||
if (c == '*') {
|
||||
c = *pattern;
|
||||
if (c == '\0') /* "*\0" matches anything remaining */
|
||||
return HOST_MATCH;
|
||||
|
||||
while (*hostname) {
|
||||
/* The only recursive function in libcurl! */
|
||||
if (hostmatch(hostname++,pattern) == HOST_MATCH)
|
||||
return HOST_MATCH;
|
||||
}
|
||||
return HOST_NOMATCH;
|
||||
}
|
||||
|
||||
if (toupper(c) != toupper(*hostname++))
|
||||
return HOST_NOMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cert_hostcheck(const char *match_pattern, const char *hostname)
|
||||
{
|
||||
if (!match_pattern || !*match_pattern ||
|
||||
!hostname || !*hostname) /* sanity check */
|
||||
return 0;
|
||||
|
||||
if(curl_strequal(certname, hostname)) /* trivial case */
|
||||
if(curl_strequal(hostname,match_pattern)) /* trivial case */
|
||||
return 1;
|
||||
|
||||
certdomain = certname + 1;
|
||||
|
||||
if((certname[0] != '*') || (certdomain[0] != '.'))
|
||||
return 0; /* not a wildcard certificate, check failed */
|
||||
|
||||
if(!strchr(certdomain+1, '.'))
|
||||
return 0; /* the certificate must have at least another dot in its name */
|
||||
|
||||
/* find 'certdomain' within 'hostname' */
|
||||
tmp = strstr(hostname, certdomain);
|
||||
if(tmp) {
|
||||
/* ok the certname's domain matches the hostname, let's check that it's a
|
||||
tail-match */
|
||||
if(curl_strequal(tmp, certdomain))
|
||||
/* looks like a match. Just check we havent swallowed a '.' */
|
||||
return tmp == strchr(hostname, '.');
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (hostmatch(hostname,match_pattern) == HOST_MATCH)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -820,19 +847,9 @@ static CURLcode verifyhost(struct connectdata *conn,
|
||||
altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
|
||||
|
||||
if(altnames) {
|
||||
int hostlen = 0;
|
||||
int domainlen = 0;
|
||||
char *domain = NULL;
|
||||
int numalts;
|
||||
int i;
|
||||
|
||||
if(GEN_DNS == target) {
|
||||
hostlen = (int)strlen(conn->host.name);
|
||||
domain = strchr(conn->host.name, '.');
|
||||
if(domain)
|
||||
domainlen = (int)strlen(domain);
|
||||
}
|
||||
|
||||
/* get amount of alternatives, RFC2459 claims there MUST be at least
|
||||
one, but we don't depend on it... */
|
||||
numalts = sk_GENERAL_NAME_num(altnames);
|
||||
@@ -846,25 +863,28 @@ static CURLcode verifyhost(struct connectdata *conn,
|
||||
if(check->type == target) {
|
||||
/* get data and length */
|
||||
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
|
||||
const int altlen = ASN1_STRING_length(check->d.ia5);
|
||||
int altlen;
|
||||
|
||||
switch(target) {
|
||||
case GEN_DNS: /* name comparison */
|
||||
/* Is this an exact match? */
|
||||
if((hostlen == altlen) &&
|
||||
curl_strnequal(conn->host.name, altptr, hostlen))
|
||||
matched = TRUE;
|
||||
case GEN_DNS: /* name/pattern comparison */
|
||||
/* The OpenSSL man page explicitly says: "In general it cannot be
|
||||
assumed that the data returned by ASN1_STRING_data() is null
|
||||
terminated or does not contain embedded nulls." But also that
|
||||
"The actual format of the data will depend on the actual string
|
||||
type itself: for example for and IA5String the data will be ASCII"
|
||||
|
||||
/* Is this a wildcard match? */
|
||||
else if((altptr[0] == '*') &&
|
||||
(domainlen == altlen-1) &&
|
||||
curl_strnequal(domain, altptr+1, domainlen))
|
||||
Gisle researched the OpenSSL sources:
|
||||
"I checked the 0.9.6 and 0.9.8 sources before my patch and
|
||||
it always 0-terminates an IA5String."
|
||||
*/
|
||||
if (cert_hostcheck(altptr, conn->host.name))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case GEN_IPADD: /* IP address comparison */
|
||||
/* compare alternative IP address if the data chunk is the same size
|
||||
our server IP address is */
|
||||
altlen = ASN1_STRING_length(check->d.ia5);
|
||||
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
|
||||
matched = TRUE;
|
||||
break;
|
||||
@@ -937,6 +957,115 @@ static CURLcode verifyhost(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions
|
||||
and thus this cannot be done there. */
|
||||
#ifdef SSL_CTRL_SET_MSG_CALLBACK
|
||||
|
||||
static const char *ssl_msg_type(int ssl_ver, int msg)
|
||||
{
|
||||
if (ssl_ver == SSL2_VERSION_MAJOR) {
|
||||
switch (msg) {
|
||||
case SSL2_MT_ERROR:
|
||||
return "Error";
|
||||
case SSL2_MT_CLIENT_HELLO:
|
||||
return "Client hello";
|
||||
case SSL2_MT_CLIENT_MASTER_KEY:
|
||||
return "Client key";
|
||||
case SSL2_MT_CLIENT_FINISHED:
|
||||
return "Client finished";
|
||||
case SSL2_MT_SERVER_HELLO:
|
||||
return "Server hello";
|
||||
case SSL2_MT_SERVER_VERIFY:
|
||||
return "Server verify";
|
||||
case SSL2_MT_SERVER_FINISHED:
|
||||
return "Server finished";
|
||||
case SSL2_MT_REQUEST_CERTIFICATE:
|
||||
return "Request CERT";
|
||||
case SSL2_MT_CLIENT_CERTIFICATE:
|
||||
return "Client CERT";
|
||||
}
|
||||
}
|
||||
else if (ssl_ver == SSL3_VERSION_MAJOR) {
|
||||
switch (msg) {
|
||||
case SSL3_MT_HELLO_REQUEST:
|
||||
return "Hello request";
|
||||
case SSL3_MT_CLIENT_HELLO:
|
||||
return "Client hello";
|
||||
case SSL3_MT_SERVER_HELLO:
|
||||
return "Server hello";
|
||||
case SSL3_MT_CERTIFICATE:
|
||||
return "CERT";
|
||||
case SSL3_MT_SERVER_KEY_EXCHANGE:
|
||||
return "Server key exchange";
|
||||
case SSL3_MT_CLIENT_KEY_EXCHANGE:
|
||||
return "Client key exchange";
|
||||
case SSL3_MT_CERTIFICATE_REQUEST:
|
||||
return "Request CERT";
|
||||
case SSL3_MT_SERVER_DONE:
|
||||
return "Server finished";
|
||||
case SSL3_MT_CERTIFICATE_VERIFY:
|
||||
return "CERT verify";
|
||||
case SSL3_MT_FINISHED:
|
||||
return "Finished";
|
||||
}
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char *tls_rt_type(int type)
|
||||
{
|
||||
return (
|
||||
type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " :
|
||||
type == SSL3_RT_ALERT ? "TLS alert, " :
|
||||
type == SSL3_RT_HANDSHAKE ? "TLS handshake, " :
|
||||
type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " :
|
||||
"TLS Unknown, ");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Our callback from the SSL/TLS layers.
|
||||
*/
|
||||
static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
|
||||
const void *buf, size_t len, const SSL *ssl,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
const char *msg_name, *tls_rt_name;
|
||||
char ssl_buf[1024];
|
||||
int ver, msg_type, txt_len;
|
||||
|
||||
if (!conn || !conn->data || !conn->data->set.fdebug ||
|
||||
(direction != 0 && direction != 1))
|
||||
return;
|
||||
|
||||
data = conn->data;
|
||||
ssl_ver >>= 8;
|
||||
ver = (ssl_ver == SSL2_VERSION_MAJOR ? '2' :
|
||||
ssl_ver == SSL3_VERSION_MAJOR ? '3' : '?');
|
||||
|
||||
/* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL
|
||||
* always pass-up content-type as 0. But the interesting message-type
|
||||
* is at 'buf[0]'.
|
||||
*/
|
||||
if (ssl_ver == SSL3_VERSION_MAJOR && content_type != 0)
|
||||
tls_rt_name = tls_rt_type(content_type);
|
||||
else
|
||||
tls_rt_name = "";
|
||||
|
||||
msg_type = *(char*)buf;
|
||||
msg_name = ssl_msg_type(ssl_ver, msg_type);
|
||||
|
||||
txt_len = 1 + sprintf(ssl_buf, "SSLv%c, %s%s (%d):\n",
|
||||
ver, tls_rt_name, msg_name, msg_type);
|
||||
Curl_debug(data, CURLINFO_TEXT, ssl_buf, txt_len, NULL);
|
||||
|
||||
Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
|
||||
CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
|
||||
(void) ssl;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ====================================================== */
|
||||
CURLcode
|
||||
Curl_SSLConnect(struct connectdata *conn,
|
||||
@@ -990,6 +1119,14 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
#ifdef SSL_CTRL_SET_MSG_CALLBACK
|
||||
if (data->set.fdebug) {
|
||||
SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
|
||||
ssl_tls_trace);
|
||||
SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, conn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* OpenSSL contains code to work-around lots of bugs and flaws in various
|
||||
SSL-implementations. SSL_CTX_set_options() is used to enabled those
|
||||
work-arounds. The man page for this option states that SSL_OP_ALL enables
|
||||
@@ -1000,6 +1137,16 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
*/
|
||||
SSL_CTX_set_options(connssl->ctx, SSL_OP_ALL);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Not sure it's needed to tell SSL_connect() that socket is
|
||||
* non-blocking. It doesn't seem to care, but just return with
|
||||
* SSL_ERROR_WANT_x.
|
||||
*/
|
||||
if (data->state.used_interface == Curl_if_multi)
|
||||
SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL);
|
||||
#endif
|
||||
|
||||
if(data->set.cert) {
|
||||
if(!cert_stuff(conn,
|
||||
connssl->ctx,
|
||||
@@ -1104,10 +1251,6 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
/* Evaluate in milliseconds how much time that has passed */
|
||||
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* get the most strict timeout of the ones converted to milliseconds */
|
||||
if(data->set.timeout &&
|
||||
(data->set.timeout>data->set.connecttimeout))
|
||||
@@ -1149,6 +1292,8 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
unsigned long errdetail;
|
||||
char error_buffer[120]; /* OpenSSL documents that this must be at least
|
||||
120 bytes long. */
|
||||
CURLcode rc;
|
||||
const char *cert_problem = NULL;
|
||||
|
||||
errdetail = ERR_get_error(); /* Gets the earliest error code from the
|
||||
thread's error queue and removes the
|
||||
@@ -1160,16 +1305,34 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
SSL routines:
|
||||
SSL2_SET_CERTIFICATE:
|
||||
certificate verify failed */
|
||||
/* fall-through */
|
||||
case 0x14090086:
|
||||
/* 14090086:
|
||||
SSL routines:
|
||||
SSL3_GET_SERVER_CERTIFICATE:
|
||||
certificate verify failed */
|
||||
failf(data,
|
||||
"SSL certificate problem, verify that the CA cert is OK");
|
||||
return CURLE_SSL_CACERT;
|
||||
cert_problem = "SSL certificate problem, verify that the CA cert is"
|
||||
" OK. Details:\n";
|
||||
rc = CURLE_SSL_CACERT;
|
||||
break;
|
||||
default:
|
||||
rc = CURLE_SSL_CONNECT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* detail is already set to the SSL error above */
|
||||
|
||||
/* If we e.g. use SSLv2 request-method and the server doesn't like us
|
||||
* (RST connection etc.), OpenSSL gives no explanation whatsoever and
|
||||
* the SO_ERROR is also lost.
|
||||
*/
|
||||
if (CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
|
||||
failf(data, "Unknown SSL protocol error in connection to %s:%d ",
|
||||
conn->host.name, conn->port);
|
||||
return rc;
|
||||
}
|
||||
/* Could be a CERT problem */
|
||||
|
||||
#ifdef HAVE_ERR_ERROR_STRING_N
|
||||
/* OpenSSL 0.9.6 and later has a function named
|
||||
ERRO_error_string_n() that takes the size of the buffer as a
|
||||
@@ -1178,10 +1341,8 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
#else
|
||||
ERR_error_string(errdetail, error_buffer);
|
||||
#endif
|
||||
|
||||
failf(data, "SSL: %s", error_buffer);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1277,18 +1438,18 @@ Curl_SSLConnect(struct connectdata *conn,
|
||||
/* We could do all sorts of certificate verification stuff here before
|
||||
deallocating the certificate. */
|
||||
|
||||
data->set.ssl.certverifyresult=SSL_get_verify_result(connssl->handle);
|
||||
err = data->set.ssl.certverifyresult=SSL_get_verify_result(connssl->handle);
|
||||
if(data->set.ssl.certverifyresult != X509_V_OK) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
/* We probably never reach this, because SSL_connect() will fail
|
||||
and we return earlyer if verifypeer is set? */
|
||||
failf(data, "SSL certificate verify result: %d",
|
||||
data->set.ssl.certverifyresult);
|
||||
failf(data, "SSL certificate verify result: %s (%d)",
|
||||
X509_verify_cert_error_string(err), err);
|
||||
retcode = CURLE_SSL_PEER_CERTIFICATE;
|
||||
}
|
||||
else
|
||||
infof(data, "SSL certificate verify result: %d, continuing anyway.\n",
|
||||
data->set.ssl.certverifyresult);
|
||||
infof(data, "SSL certificate verify result: %s (%d), continuing anyway.\n",
|
||||
X509_verify_cert_error_string(err), err);
|
||||
}
|
||||
else
|
||||
infof(data, "SSL certificate verify ok.\n");
|
||||
|
@@ -78,6 +78,25 @@ int curl_strnequal(const char *first, const char *second, size_t max)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_strcasestr() finds the first occurrence of the substring needle in the
|
||||
* string haystack. The terminating `\0' characters are not compared. The
|
||||
* matching is done CASE INSENSITIVE, which thus is the difference between
|
||||
* this and strstr().
|
||||
*/
|
||||
char *Curl_strcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t nlen = strlen(needle);
|
||||
size_t hlen = strlen(haystack);
|
||||
|
||||
while(hlen-- >= nlen) {
|
||||
if(curl_strnequal(haystack, needle, nlen))
|
||||
return (char *)haystack;
|
||||
haystack++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
/*
|
||||
* The strlcat() function appends the NUL-terminated string src to the end
|
||||
|
@@ -36,6 +36,9 @@ int curl_strnequal(const char *first, const char *second, size_t max);
|
||||
argument is zero-byte terminated */
|
||||
#define checkprefix(a,b) strnequal(a,b,strlen(a))
|
||||
|
||||
/* case insensitive strstr() */
|
||||
char *Curl_strcasestr(const char *haystack, const char *needle);
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
#define strlcat(x,y,z) Curl_strlcat(x,y,z)
|
||||
size_t Curl_strlcat(char *dst, const char *src, size_t siz);
|
||||
|
@@ -37,7 +37,8 @@
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
#if !defined(_WINSOCKAPI_) && !defined(__MINGW32__) && !defined(_AMIGASF)
|
||||
#if !defined(_WINSOCKAPI_) && !defined(__MINGW32__) && !defined(_AMIGASF) && \
|
||||
!defined(__LCC__)
|
||||
struct timeval {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
|
168
lib/transfer.c
168
lib/transfer.c
@@ -125,8 +125,9 @@ static struct timeval notimeout={0,0};
|
||||
* This function will call the read callback to fill our buffer with data
|
||||
* to upload.
|
||||
*/
|
||||
int Curl_fillreadbuffer(struct connectdata *conn, int bytes)
|
||||
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
int buffersize = bytes;
|
||||
int nread;
|
||||
|
||||
@@ -139,6 +140,11 @@ int Curl_fillreadbuffer(struct connectdata *conn, int bytes)
|
||||
nread = conn->fread(conn->upload_fromhere, 1,
|
||||
buffersize, conn->fread_in);
|
||||
|
||||
if(nread == CURL_READFUNC_ABORT) {
|
||||
failf(data, "operation aborted by callback\n");
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
|
||||
if(!conn->bits.forbidchunk && conn->bits.upload_chunky) {
|
||||
/* if chunked Transfer-Encoding */
|
||||
char hexbuffer[11];
|
||||
@@ -161,7 +167,10 @@ int Curl_fillreadbuffer(struct connectdata *conn, int bytes)
|
||||
|
||||
nread+=2; /* for the added CRLF */
|
||||
}
|
||||
return nread;
|
||||
|
||||
*nreadp = nread;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -187,6 +196,7 @@ checkhttpprefix(struct SessionHandle *data,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_readwrite() is the low-level function to be called when data is to
|
||||
* be read and written to/from the connection.
|
||||
@@ -442,6 +452,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
FD_ZERO(&k->wkeepfd);
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
/*
|
||||
* When all the headers have been parsed, see if we should give
|
||||
* up and return an error.
|
||||
@@ -451,6 +462,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
k->httpcode);
|
||||
return CURLE_HTTP_RETURNED_ERROR;
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
/* now, only output this if the header AND body are requested:
|
||||
*/
|
||||
@@ -488,7 +500,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
return CURLE_HTTP_RANGE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(!stop_reading) {
|
||||
/* Curl_http_auth_act() checks what authentication methods
|
||||
* that are available and decides which one (if any) to
|
||||
@@ -498,6 +510,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
if(!k->header) {
|
||||
/*
|
||||
@@ -696,6 +709,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
data->info.contenttype[len] = 0; /* zero terminate */
|
||||
}
|
||||
}
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
else if((k->httpversion == 10) &&
|
||||
conn->bits.httpproxy &&
|
||||
Curl_compareheader(k->p,
|
||||
@@ -864,6 +878,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
/*
|
||||
* End of header-checks. Write them to the client.
|
||||
@@ -875,7 +890,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
|
||||
if(data->set.verbose)
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
k->p, k->hbuflen);
|
||||
k->p, k->hbuflen, conn->host.dispname);
|
||||
|
||||
result = Curl_client_write(data, writetype, k->p, k->hbuflen);
|
||||
if(result)
|
||||
@@ -962,14 +977,17 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
if(data->set.verbose) {
|
||||
if(k->badheader) {
|
||||
Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
|
||||
k->hbuflen);
|
||||
k->hbuflen, conn->host.dispname);
|
||||
if(k->badheader == HEADER_PARTHEADER)
|
||||
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread);
|
||||
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread,
|
||||
conn->host.dispname);
|
||||
}
|
||||
else
|
||||
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread);
|
||||
Curl_debug(data, CURLINFO_DATA_IN, k->str, nread,
|
||||
conn->host.dispname);
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(conn->bits.chunk) {
|
||||
/*
|
||||
* Bless me father for I have sinned. Here comes a chunked
|
||||
@@ -999,6 +1017,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
}
|
||||
/* If it returned OK, we just keep going */
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
if((-1 != conn->maxdownload) &&
|
||||
(k->bytecount + nread >= conn->maxdownload)) {
|
||||
@@ -1107,6 +1126,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
if(!k->upload_done) {
|
||||
/* HTTP pollution, this should be written nicer to become more
|
||||
protocol agnostic. */
|
||||
int fillcount;
|
||||
|
||||
if(k->wait100_after_headers &&
|
||||
(conn->proto.http->sending == HTTPSEND_BODY)) {
|
||||
@@ -1123,7 +1143,11 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
break;
|
||||
}
|
||||
|
||||
nread = Curl_fillreadbuffer(conn, BUFSIZE);
|
||||
result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
nread = (ssize_t)fillcount;
|
||||
}
|
||||
else
|
||||
nread = 0; /* we're done uploading/reading */
|
||||
@@ -1187,7 +1211,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
if(data->set.verbose)
|
||||
/* show the data before we change the pointer upload_fromhere */
|
||||
Curl_debug(data, CURLINFO_DATA_OUT, conn->upload_fromhere,
|
||||
bytes_written);
|
||||
bytes_written, conn->host.dispname);
|
||||
|
||||
if(conn->upload_present != bytes_written) {
|
||||
/* we only wrote a part of the buffer (if anything), deal with it! */
|
||||
@@ -1302,6 +1326,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_readwrite_init() inits the readwrite session.
|
||||
*/
|
||||
@@ -1517,6 +1542,7 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
|
||||
data->state.authhost.want = data->set.httpauth;
|
||||
data->state.authproxy.want = data->set.proxyauth;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
/* If there was a list of cookie files to read and we haven't done it before,
|
||||
do it now! */
|
||||
if(data->change.cookielist) {
|
||||
@@ -1533,7 +1559,7 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
|
||||
curl_slist_free_all(data->change.cookielist); /* clean up list */
|
||||
data->change.cookielist = NULL; /* don't do this again! */
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
|
||||
/* Allow data->set.use_port to set which port to use. This needs to be
|
||||
@@ -1919,6 +1945,50 @@ CURLcode Curl_follow(struct SessionHandle *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
Curl_connect_host(struct SessionHandle *data,
|
||||
struct connectdata **conn)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
int urlchanged = FALSE;
|
||||
|
||||
do {
|
||||
bool async;
|
||||
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
||||
data->change.url_changed = FALSE;
|
||||
res = Curl_connect(data, conn, &async);
|
||||
|
||||
if((CURLE_OK == res) && async) {
|
||||
/* Now, if async is TRUE here, we need to wait for the name
|
||||
to resolve */
|
||||
res = Curl_wait_for_resolv(*conn, NULL);
|
||||
if(CURLE_OK == res)
|
||||
/* Resolved, continue with the connection */
|
||||
res = Curl_async_resolved(*conn);
|
||||
}
|
||||
if(res)
|
||||
break;
|
||||
|
||||
/* If a callback (or something) has altered the URL we should use within
|
||||
the Curl_connect(), we detect it here and act as if we are redirected
|
||||
to the new URL */
|
||||
urlchanged = data->change.url_changed;
|
||||
if ((CURLE_OK == res) && urlchanged) {
|
||||
res = Curl_done(conn, res);
|
||||
if(CURLE_OK == res) {
|
||||
char *gotourl = strdup(data->change.url);
|
||||
res = Curl_follow(data, gotourl);
|
||||
if(res)
|
||||
free(gotourl);
|
||||
}
|
||||
}
|
||||
} while (urlchanged && res == CURLE_OK);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Curl_perform() is the internal high-level function that gets called by the
|
||||
* external curl_easy_perform() function. It inits, performs and cleans up a
|
||||
@@ -1945,43 +2015,21 @@ CURLcode Curl_perform(struct SessionHandle *data)
|
||||
*/
|
||||
|
||||
do {
|
||||
int urlchanged = FALSE;
|
||||
do {
|
||||
bool async;
|
||||
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
||||
data->change.url_changed = FALSE;
|
||||
res = Curl_connect(data, &conn, &async);
|
||||
|
||||
if((CURLE_OK == res) && async) {
|
||||
/* Now, if async is TRUE here, we need to wait for the name
|
||||
to resolve */
|
||||
res = Curl_wait_for_resolv(conn, NULL);
|
||||
if(CURLE_OK == res)
|
||||
/* Resolved, continue with the connection */
|
||||
res = Curl_async_resolved(conn);
|
||||
}
|
||||
if(res)
|
||||
break;
|
||||
|
||||
/* If a callback (or something) has altered the URL we should use within
|
||||
the Curl_connect(), we detect it here and act as if we are redirected
|
||||
to the new URL */
|
||||
urlchanged = data->change.url_changed;
|
||||
if ((CURLE_OK == res) && urlchanged) {
|
||||
res = Curl_done(&conn, res);
|
||||
if(CURLE_OK == res) {
|
||||
char *gotourl = strdup(data->change.url);
|
||||
res = Curl_follow(data, gotourl);
|
||||
if(res)
|
||||
free(gotourl);
|
||||
}
|
||||
}
|
||||
} while (urlchanged && res == CURLE_OK);
|
||||
res = Curl_connect_host(data, &conn); /* primary connection */
|
||||
|
||||
if(res == CURLE_OK) {
|
||||
if (data->set.source_host) /* 3rd party transfer */
|
||||
res = Curl_pretransfersec(conn);
|
||||
else
|
||||
conn->sec_conn = NULL;
|
||||
}
|
||||
|
||||
if(res == CURLE_OK) {
|
||||
|
||||
res = Curl_do(&conn);
|
||||
|
||||
if(res == CURLE_OK) {
|
||||
/* for non 3rd party transfer only */
|
||||
if(res == CURLE_OK && !data->set.source_host) {
|
||||
res = Transfer(conn); /* now fetch that URL please */
|
||||
if(res == CURLE_OK) {
|
||||
|
||||
@@ -2099,3 +2147,37 @@ Curl_Transfer(struct connectdata *c_conn, /* connection data */
|
||||
return CURLE_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_pretransfersec() prepares the secondary connection (used for 3rd party
|
||||
* FTP transfers).
|
||||
*/
|
||||
CURLcode Curl_pretransfersec(struct connectdata *conn)
|
||||
{
|
||||
CURLcode status = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct connectdata *sec_conn = NULL; /* secondary connection */
|
||||
|
||||
/* update data with source host options */
|
||||
char *url = aprintf( "%s://%s/", conn->protostr, data->set.source_host);
|
||||
|
||||
if(!url)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(data->change.url_alloc)
|
||||
free(data->change.url);
|
||||
|
||||
data->change.url_alloc = TRUE;
|
||||
data->change.url = url;
|
||||
data->set.ftpport = data->set.source_port;
|
||||
data->set.userpwd = data->set.source_userpwd;
|
||||
|
||||
/* secondary connection */
|
||||
status = Curl_connect_host(data, &sec_conn);
|
||||
if(CURLE_OK == status) {
|
||||
sec_conn->data = data;
|
||||
conn->sec_conn = sec_conn;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@
|
||||
***************************************************************************/
|
||||
CURLcode Curl_perform(struct SessionHandle *data);
|
||||
CURLcode Curl_pretransfer(struct SessionHandle *data);
|
||||
CURLcode Curl_pretransfersec(struct connectdata *conn);
|
||||
CURLcode Curl_posttransfer(struct SessionHandle *data);
|
||||
CURLcode Curl_follow(struct SessionHandle *data, char *newurl);
|
||||
CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
|
||||
@@ -34,7 +35,7 @@ void Curl_single_fdset(struct connectdata *conn,
|
||||
int *max_fd);
|
||||
CURLcode Curl_readwrite_init(struct connectdata *conn);
|
||||
|
||||
int Curl_fillreadbuffer(struct connectdata *conn, int bytes);
|
||||
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
|
||||
|
||||
/* This sets up a forthcoming transfer */
|
||||
CURLcode
|
||||
|
584
lib/url.c
584
lib/url.c
@@ -238,6 +238,8 @@ CURLcode Curl_close(struct SessionHandle *data)
|
||||
Curl_cookie_cleanup(data->cookies);
|
||||
}
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
|
||||
|
||||
Curl_digest_cleanup(data);
|
||||
#endif
|
||||
|
||||
/* free the connection cache */
|
||||
@@ -245,8 +247,6 @@ CURLcode Curl_close(struct SessionHandle *data)
|
||||
|
||||
Curl_safefree(data->info.contenttype);
|
||||
|
||||
Curl_digest_cleanup(data);
|
||||
|
||||
#ifdef USE_ARES
|
||||
/* this destroys the channel and we cannot use it anymore after this */
|
||||
ares_destroy(data->state.areschannel);
|
||||
@@ -499,8 +499,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
data->set.http_fail_on_error = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
case CURLOPT_UPLOAD:
|
||||
case CURLOPT_PUT:
|
||||
/*
|
||||
* We want to sent data to the remote host
|
||||
* We want to sent data to the remote host. If this is HTTP, that equals
|
||||
* using the PUT request.
|
||||
*/
|
||||
data->set.upload = va_arg(param, long)?TRUE:FALSE;
|
||||
if(data->set.upload)
|
||||
@@ -553,27 +555,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
*/
|
||||
data->set.netrc_file = va_arg(param, char *);
|
||||
break;
|
||||
case CURLOPT_FOLLOWLOCATION:
|
||||
/*
|
||||
* Follow Location: header hints on a HTTP-server.
|
||||
*/
|
||||
data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
case CURLOPT_UNRESTRICTED_AUTH:
|
||||
/*
|
||||
* Send authentication (user+password) when following locations, even when
|
||||
* hostname changed.
|
||||
*/
|
||||
data->set.http_disable_hostname_check_before_authentication =
|
||||
va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
case CURLOPT_HTTP_VERSION:
|
||||
/*
|
||||
* This sets a requested HTTP version to be used. The value is one of
|
||||
* the listed enums in curl/curl.h.
|
||||
*/
|
||||
data->set.httpversion = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_TRANSFERTEXT:
|
||||
/*
|
||||
* This option was previously named 'FTPASCII'. Renamed to work with
|
||||
@@ -583,14 +564,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
*/
|
||||
data->set.ftp_ascii = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
case CURLOPT_PUT:
|
||||
/*
|
||||
* Use the HTTP PUT request to transfer data if this is TRUE. If this is
|
||||
* FALSE, don't set the httpreq. We can't know what to revert it to!
|
||||
*/
|
||||
if(va_arg(param, long))
|
||||
data->set.httpreq = HTTPREQ_PUT;
|
||||
break;
|
||||
case CURLOPT_TIMECONDITION:
|
||||
/*
|
||||
* Set HTTP time condition. This must be one of the defines in the
|
||||
@@ -613,26 +586,135 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
data->set.ssl.version = va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_COOKIESESSION:
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
case CURLOPT_AUTOREFERER:
|
||||
/*
|
||||
* 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.
|
||||
* Switch on automatic referer that gets set if curl follows locations.
|
||||
*/
|
||||
data->set.cookiesession = (bool)va_arg(param, long);
|
||||
data->set.http_auto_referer = va_arg(param, long)?1:0;
|
||||
break;
|
||||
|
||||
case CURLOPT_ENCODING:
|
||||
/*
|
||||
* String to use at the value of Accept-Encoding header.
|
||||
*
|
||||
* If the encoding is set to "" we use an Accept-Encoding header that
|
||||
* encompasses all the encodings we support.
|
||||
* If the encoding is set to NULL we don't send an Accept-Encoding header
|
||||
* and ignore an received Content-Encoding header.
|
||||
*
|
||||
*/
|
||||
data->set.encoding = va_arg(param, char *);
|
||||
if(data->set.encoding && !*data->set.encoding)
|
||||
data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
|
||||
break;
|
||||
|
||||
case CURLOPT_FOLLOWLOCATION:
|
||||
/*
|
||||
* Follow Location: header hints on a HTTP-server.
|
||||
*/
|
||||
data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
|
||||
case CURLOPT_UNRESTRICTED_AUTH:
|
||||
/*
|
||||
* Send authentication (user+password) when following locations, even when
|
||||
* hostname changed.
|
||||
*/
|
||||
data->set.http_disable_hostname_check_before_authentication =
|
||||
va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
|
||||
case CURLOPT_MAXREDIRS:
|
||||
/*
|
||||
* The maximum amount of hops you allow curl to follow Location:
|
||||
* headers. This should mostly be used to detect never-ending loops.
|
||||
*/
|
||||
data->set.maxredirs = va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_POST:
|
||||
/* Does this option serve a purpose anymore? Yes it does, when
|
||||
CURLOPT_POSTFIELDS isn't used and the POST data is read off the
|
||||
callback! */
|
||||
if(va_arg(param, long))
|
||||
data->set.httpreq = HTTPREQ_POST;
|
||||
break;
|
||||
|
||||
case CURLOPT_POSTFIELDS:
|
||||
/*
|
||||
* A string with POST data. Makes curl HTTP POST.
|
||||
*/
|
||||
data->set.postfields = va_arg(param, char *);
|
||||
if(data->set.postfields)
|
||||
data->set.httpreq = HTTPREQ_POST;
|
||||
break;
|
||||
|
||||
case CURLOPT_POSTFIELDSIZE:
|
||||
/*
|
||||
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
|
||||
* figure it out. Enables binary posts.
|
||||
*/
|
||||
data->set.postfieldsize = va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_POSTFIELDSIZE_LARGE:
|
||||
/*
|
||||
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
|
||||
* figure it out. Enables binary posts.
|
||||
*/
|
||||
data->set.postfieldsize = va_arg(param, curl_off_t);
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPPOST:
|
||||
/*
|
||||
* Set to make us do HTTP POST
|
||||
*/
|
||||
data->set.httppost = va_arg(param, struct curl_httppost *);
|
||||
if(data->set.httppost)
|
||||
data->set.httpreq = HTTPREQ_POST_FORM;
|
||||
break;
|
||||
|
||||
case CURLOPT_REFERER:
|
||||
/*
|
||||
* String to set in the HTTP Referer: field.
|
||||
*/
|
||||
if(data->change.referer_alloc) {
|
||||
free(data->change.referer);
|
||||
data->change.referer_alloc = FALSE;
|
||||
}
|
||||
data->set.set_referer = va_arg(param, char *);
|
||||
data->change.referer = data->set.set_referer;
|
||||
break;
|
||||
|
||||
case CURLOPT_USERAGENT:
|
||||
/*
|
||||
* String to use in the HTTP User-Agent field
|
||||
*/
|
||||
data->set.useragent = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPHEADER:
|
||||
/*
|
||||
* Set a list with HTTP headers to use (or replace internals with)
|
||||
*/
|
||||
data->set.headers = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTP200ALIASES:
|
||||
/*
|
||||
* Set a list of aliases for HTTP 200 in response header
|
||||
*/
|
||||
data->set.http200aliases = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
|
||||
case CURLOPT_COOKIE:
|
||||
/*
|
||||
* Cookie string to send to the remote server in the request.
|
||||
*/
|
||||
data->set.cookie = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
case CURLOPT_COOKIEFILE:
|
||||
/*
|
||||
* Set cookie file to read and parse. Can be used multiple times.
|
||||
@@ -664,7 +746,131 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
data->cookies = Curl_cookie_init(data, NULL, data->cookies,
|
||||
data->set.cookiesession);
|
||||
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;
|
||||
|
||||
case CURLOPT_HTTPGET:
|
||||
/*
|
||||
* Set to force us do HTTP GET
|
||||
*/
|
||||
if(va_arg(param, long)) {
|
||||
data->set.httpreq = HTTPREQ_GET;
|
||||
data->set.upload = FALSE; /* switch off upload */
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTP_VERSION:
|
||||
/*
|
||||
* This sets a requested HTTP version to be used. The value is one of
|
||||
* the listed enums in curl/curl.h.
|
||||
*/
|
||||
data->set.httpversion = va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPPROXYTUNNEL:
|
||||
/*
|
||||
* Tunnel operations through the proxy instead of normal proxy use
|
||||
*/
|
||||
data->set.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
|
||||
case CURLOPT_CUSTOMREQUEST:
|
||||
/*
|
||||
* Set a custom string to use as request
|
||||
*/
|
||||
data->set.customrequest = va_arg(param, char *);
|
||||
|
||||
/* we don't set
|
||||
data->set.httpreq = HTTPREQ_CUSTOM;
|
||||
here, we continue as if we were using the already set type
|
||||
and this just changes the actual request keyword */
|
||||
break;
|
||||
|
||||
case CURLOPT_PROXY:
|
||||
/*
|
||||
* Set proxy server:port to use as HTTP proxy.
|
||||
*
|
||||
* If the proxy is set to "" we explicitly say that we don't want to use a
|
||||
* proxy (even though there might be environment variables saying so).
|
||||
*
|
||||
* Setting it to NULL, means no proxy but allows the environment variables
|
||||
* to decide for us.
|
||||
*/
|
||||
if(data->change.proxy_alloc) {
|
||||
/*
|
||||
* The already set string is allocated, free that first
|
||||
*/
|
||||
data->change.proxy_alloc=FALSE;;
|
||||
free(data->change.proxy);
|
||||
}
|
||||
data->set.set_proxy = va_arg(param, char *);
|
||||
data->change.proxy = data->set.set_proxy;
|
||||
break;
|
||||
|
||||
case CURLOPT_PROXYPORT:
|
||||
/*
|
||||
* Explicitly set HTTP proxy port number.
|
||||
*/
|
||||
data->set.proxyport = va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPAUTH:
|
||||
/*
|
||||
* Set HTTP Authentication type BITMASK.
|
||||
*/
|
||||
{
|
||||
long auth = va_arg(param, long);
|
||||
/* switch off bits we can't support */
|
||||
#ifndef USE_SSLEAY
|
||||
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
|
||||
#endif
|
||||
#ifndef HAVE_GSSAPI
|
||||
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
|
||||
#endif
|
||||
if(!auth)
|
||||
return CURLE_FAILED_INIT; /* no supported types left! */
|
||||
|
||||
data->set.httpauth = auth;
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_PROXYAUTH:
|
||||
/*
|
||||
* Set HTTP Authentication type BITMASK.
|
||||
*/
|
||||
{
|
||||
long auth = va_arg(param, long);
|
||||
/* switch off bits we can't support */
|
||||
#ifndef USE_SSLEAY
|
||||
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
|
||||
#endif
|
||||
#ifndef HAVE_GSSAPI
|
||||
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
|
||||
#endif
|
||||
if(!auth)
|
||||
return CURLE_FAILED_INIT; /* no supported types left! */
|
||||
|
||||
data->set.proxyauth = auth;
|
||||
}
|
||||
break;
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
case CURLOPT_WRITEHEADER:
|
||||
/*
|
||||
@@ -672,12 +878,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
*/
|
||||
data->set.writeheader = (void *)va_arg(param, void *);
|
||||
break;
|
||||
case CURLOPT_COOKIE:
|
||||
/*
|
||||
* Cookie string to send to the remote server in the request.
|
||||
*/
|
||||
data->set.cookie = va_arg(param, char *);
|
||||
break;
|
||||
case CURLOPT_ERRORBUFFER:
|
||||
/*
|
||||
* Error buffer provided by the caller to get the human readable
|
||||
@@ -707,42 +907,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPHEADER:
|
||||
/*
|
||||
* Set a list with HTTP headers to use (or replace internals with)
|
||||
*/
|
||||
data->set.headers = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
case CURLOPT_CUSTOMREQUEST:
|
||||
/*
|
||||
* Set a custom string to use as request
|
||||
*/
|
||||
data->set.customrequest = va_arg(param, char *);
|
||||
|
||||
/* we don't set
|
||||
data->set.httpreq = HTTPREQ_CUSTOM;
|
||||
here, we continue as if we were using the already set type
|
||||
and this just changes the actual request keyword */
|
||||
break;
|
||||
case CURLOPT_HTTPPOST:
|
||||
/*
|
||||
* Set to make us do HTTP POST
|
||||
*/
|
||||
data->set.httppost = va_arg(param, struct curl_httppost *);
|
||||
if(data->set.httppost)
|
||||
data->set.httpreq = HTTPREQ_POST_FORM;
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPGET:
|
||||
/*
|
||||
* Set to force us do HTTP GET
|
||||
*/
|
||||
if(va_arg(param, long)) {
|
||||
data->set.httpreq = HTTPREQ_GET;
|
||||
data->set.upload = FALSE; /* switch off upload */
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_INFILE:
|
||||
/*
|
||||
* FILE pointer to read the file to be uploaded from. Or possibly
|
||||
@@ -797,84 +961,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
*/
|
||||
data->set.use_port = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_POST:
|
||||
/* Does this option serve a purpose anymore? Yes it does, when
|
||||
CURLOPT_POSTFIELDS isn't used and the POST data is read off the
|
||||
callback! */
|
||||
if(va_arg(param, long))
|
||||
data->set.httpreq = HTTPREQ_POST;
|
||||
break;
|
||||
case CURLOPT_POSTFIELDS:
|
||||
/*
|
||||
* A string with POST data. Makes curl HTTP POST.
|
||||
*/
|
||||
data->set.postfields = va_arg(param, char *);
|
||||
if(data->set.postfields)
|
||||
data->set.httpreq = HTTPREQ_POST;
|
||||
break;
|
||||
case CURLOPT_POSTFIELDSIZE:
|
||||
/*
|
||||
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
|
||||
* figure it out. Enables binary posts.
|
||||
*/
|
||||
data->set.postfieldsize = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_POSTFIELDSIZE_LARGE:
|
||||
/*
|
||||
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
|
||||
* figure it out. Enables binary posts.
|
||||
*/
|
||||
data->set.postfieldsize = va_arg(param, curl_off_t);
|
||||
break;
|
||||
case CURLOPT_REFERER:
|
||||
/*
|
||||
* String to set in the HTTP Referer: field.
|
||||
*/
|
||||
if(data->change.referer_alloc) {
|
||||
free(data->change.referer);
|
||||
data->change.referer_alloc = FALSE;
|
||||
}
|
||||
data->set.set_referer = va_arg(param, char *);
|
||||
data->change.referer = data->set.set_referer;
|
||||
break;
|
||||
case CURLOPT_AUTOREFERER:
|
||||
/*
|
||||
* Switch on automatic referer that gets set if curl follows locations.
|
||||
*/
|
||||
data->set.http_auto_referer = va_arg(param, long)?1:0;
|
||||
break;
|
||||
case CURLOPT_PROXY:
|
||||
/*
|
||||
* Set proxy server:port to use as HTTP proxy.
|
||||
*
|
||||
* If the proxy is set to "" we explicitly say that we don't want to use a
|
||||
* proxy (even though there might be environment variables saying so).
|
||||
*
|
||||
* Setting it to NULL, means no proxy but allows the environment variables
|
||||
* to decide for us.
|
||||
*/
|
||||
if(data->change.proxy_alloc) {
|
||||
/*
|
||||
* The already set string is allocated, free that first
|
||||
*/
|
||||
data->change.proxy_alloc=FALSE;;
|
||||
free(data->change.proxy);
|
||||
}
|
||||
data->set.set_proxy = va_arg(param, char *);
|
||||
data->change.proxy = data->set.set_proxy;
|
||||
break;
|
||||
case CURLOPT_HTTPPROXYTUNNEL:
|
||||
/*
|
||||
* Tunnel operations through the proxy instead of normal proxy use
|
||||
*/
|
||||
data->set.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
|
||||
break;
|
||||
case CURLOPT_PROXYPORT:
|
||||
/*
|
||||
* Explicitly set HTTP proxy port number.
|
||||
*/
|
||||
data->set.proxyport = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_TIMEOUT:
|
||||
/*
|
||||
* The maximum time you allow curl to use for a single transfer
|
||||
@@ -888,73 +974,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
*/
|
||||
data->set.connecttimeout = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_MAXREDIRS:
|
||||
/*
|
||||
* The maximum amount of hops you allow curl to follow Location:
|
||||
* headers. This should mostly be used to detect never-ending loops.
|
||||
*/
|
||||
data->set.maxredirs = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_USERAGENT:
|
||||
/*
|
||||
* String to use in the HTTP User-Agent field
|
||||
*/
|
||||
data->set.useragent = va_arg(param, char *);
|
||||
break;
|
||||
case CURLOPT_ENCODING:
|
||||
/*
|
||||
* String to use at the value of Accept-Encoding header.
|
||||
*
|
||||
* If the encoding is set to "" we use an Accept-Encoding header that
|
||||
* encompasses all the encodings we support.
|
||||
* If the encoding is set to NULL we don't send an Accept-Encoding header
|
||||
* and ignore an received Content-Encoding header.
|
||||
*
|
||||
*/
|
||||
data->set.encoding = va_arg(param, char *);
|
||||
if(data->set.encoding && !*data->set.encoding)
|
||||
data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTPAUTH:
|
||||
/*
|
||||
* Set HTTP Authentication type BITMASK.
|
||||
*/
|
||||
{
|
||||
long auth = va_arg(param, long);
|
||||
/* switch off bits we can't support */
|
||||
#ifndef USE_SSLEAY
|
||||
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
|
||||
#endif
|
||||
#ifndef HAVE_GSSAPI
|
||||
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
|
||||
#endif
|
||||
if(!auth)
|
||||
return CURLE_FAILED_INIT; /* no supported types left! */
|
||||
|
||||
data->set.httpauth = auth;
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_PROXYAUTH:
|
||||
/*
|
||||
* Set HTTP Authentication type BITMASK.
|
||||
*/
|
||||
{
|
||||
long auth = va_arg(param, long);
|
||||
/* switch off bits we can't support */
|
||||
#ifndef USE_SSLEAY
|
||||
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
|
||||
#endif
|
||||
#ifndef HAVE_GSSAPI
|
||||
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
|
||||
#endif
|
||||
if(!auth)
|
||||
return CURLE_FAILED_INIT; /* no supported types left! */
|
||||
|
||||
data->set.proxyauth = auth;
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_USERPWD:
|
||||
/*
|
||||
@@ -1268,22 +1287,22 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
|
||||
data->hostcache = data->share->hostcache;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(data->share->cookies) {
|
||||
/* use shared cookie list, first free own one if any */
|
||||
if (data->cookies)
|
||||
Curl_cookie_cleanup(data->cookies);
|
||||
data->cookies = data->share->cookies;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
|
||||
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
/* check cookie list is set */
|
||||
if(!data->cookies)
|
||||
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE );
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
/* check for host cache not needed,
|
||||
* it will be done by curl_easy_perform */
|
||||
}
|
||||
@@ -1303,13 +1322,6 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
data->set.private = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_HTTP200ALIASES:
|
||||
/*
|
||||
* Set a list of aliases for HTTP 200 in response header
|
||||
*/
|
||||
data->set.http200aliases = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
|
||||
case CURLOPT_MAXFILESIZE:
|
||||
/*
|
||||
* Set the maximum size of a file to download.
|
||||
@@ -1343,6 +1355,57 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
||||
data->set.tcp_nodelay = (bool)va_arg(param, long);
|
||||
break;
|
||||
|
||||
/*********** 3rd party transfer options ***********/
|
||||
case CURLOPT_SOURCE_HOST:
|
||||
/*
|
||||
* Use SOURCE HOST
|
||||
*/
|
||||
data->set.source_host = va_arg(param, char *);
|
||||
data->set.printhost = (data->set.source_host != NULL);
|
||||
break;
|
||||
|
||||
case CURLOPT_SOURCE_PORT:
|
||||
/*
|
||||
* Use SOURCE PORT
|
||||
*/
|
||||
data->set.source_port = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_SOURCE_USERPWD:
|
||||
/*
|
||||
* Use SOURCE USER[:PASSWORD]
|
||||
*/
|
||||
data->set.source_userpwd = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_SOURCE_PATH:
|
||||
/*
|
||||
* Use SOURCE PATH
|
||||
*/
|
||||
data->set.source_path = va_arg(param, char *);
|
||||
break;
|
||||
|
||||
case CURLOPT_PASV_HOST:
|
||||
/*
|
||||
* Indicates whether source or target host is passive
|
||||
*/
|
||||
data->set.pasvHost = va_arg(param, long)?CURL_SOURCE_PASV:CURL_TARGET_PASV;
|
||||
break;
|
||||
|
||||
case CURLOPT_SOURCE_PREQUOTE:
|
||||
/*
|
||||
* List of RAW FTP commands to use before a transfer on the source host
|
||||
*/
|
||||
data->set.source_prequote = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
|
||||
case CURLOPT_SOURCE_POSTQUOTE:
|
||||
/*
|
||||
* List of RAW FTP commands to use after a transfer on the source host
|
||||
*/
|
||||
data->set.source_postquote = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown tag and its companion, just ignore: */
|
||||
return CURLE_FAILED_INIT; /* correct this */
|
||||
@@ -1829,7 +1892,7 @@ static int handleSock5Proxy(const char *proxy_name,
|
||||
}
|
||||
#else
|
||||
failf(conn->data,
|
||||
"%s:%d has an internal error an needs to be fixed to work",
|
||||
"%s:%d has an internal error and needs to be fixed to work",
|
||||
__FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
@@ -1877,6 +1940,11 @@ static CURLcode ConnectPlease(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result;
|
||||
Curl_ipconnect *addr;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *hostname = data->change.proxy?conn->proxy.name:conn->host.name;
|
||||
|
||||
infof(data, "About to connect() to %s port %d\n",
|
||||
hostname, conn->port);
|
||||
|
||||
/*************************************************************
|
||||
* Connect to server/proxy
|
||||
@@ -1927,22 +1995,18 @@ static CURLcode ConnectPlease(struct connectdata *conn,
|
||||
static void verboseconnect(struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
const char *host=NULL;
|
||||
char addrbuf[256];
|
||||
char addrbuf[256] = "";
|
||||
#ifdef ENABLE_IPV6
|
||||
const Curl_ipconnect *addr = conn->serv_addr;
|
||||
#else
|
||||
const Curl_ipconnect *addr = &conn->serv_addr.sin_addr;
|
||||
#endif
|
||||
|
||||
/* Get a printable version of the network address. */
|
||||
#ifdef ENABLE_IPV6
|
||||
struct addrinfo *ai = conn->serv_addr;
|
||||
host = Curl_printable_address(ai->ai_family, ai->ai_addr,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
#else
|
||||
struct in_addr in;
|
||||
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
||||
host = Curl_inet_ntop(AF_INET, &in, addrbuf, sizeof(addrbuf));
|
||||
#endif
|
||||
Curl_printable_address(addr, addrbuf, sizeof(addrbuf));
|
||||
infof(data, "Connected to %s (%s) port %d\n",
|
||||
conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname,
|
||||
host?host:"", conn->port);
|
||||
conn->bits.httpproxy ? conn->proxy.dispname : conn->host.dispname,
|
||||
addrbuf[0] ? addrbuf : "??", conn->port);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -185,6 +185,12 @@ typedef enum {
|
||||
NTLMSTATE_LAST
|
||||
} curlntlm;
|
||||
|
||||
/* for 3rd party transfers to decide which side that issues PASV */
|
||||
typedef enum {
|
||||
CURL_TARGET_PASV,
|
||||
CURL_SOURCE_PASV
|
||||
} curl_pasv_side;
|
||||
|
||||
/* Struct used for NTLM challenge-response authentication */
|
||||
struct ntlmdata {
|
||||
curlntlm state;
|
||||
@@ -313,6 +319,9 @@ struct ConnectBits {
|
||||
This is implicit when SSL-protocols are used through
|
||||
proxies, but can also be enabled explicitly by
|
||||
apps */
|
||||
bool authprobe; /* set TRUE when this transfer is done to probe for auth
|
||||
types, as when asking for "any" type when speaking
|
||||
HTTP */
|
||||
};
|
||||
|
||||
struct hostname {
|
||||
@@ -329,16 +338,16 @@ struct hostname {
|
||||
*/
|
||||
|
||||
struct Curl_transfer_keeper {
|
||||
curl_off_t bytecount; /* total number of bytes read */
|
||||
int writebytecount; /* number of bytes written */
|
||||
curl_off_t bytecount; /* total number of bytes read */
|
||||
curl_off_t writebytecount; /* number of bytes written */
|
||||
struct timeval start; /* transfer started at this time */
|
||||
struct timeval now; /* current time */
|
||||
bool header; /* incoming data has HTTP header */
|
||||
enum {
|
||||
HEADER_NORMAL, /* no bad header at all */
|
||||
HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest is
|
||||
normal data */
|
||||
HEADER_ALLBAD /* all was believed to be header */
|
||||
HEADER_NORMAL, /* no bad header at all */
|
||||
HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
|
||||
is normal data */
|
||||
HEADER_ALLBAD /* all was believed to be header */
|
||||
} badheader; /* the header was deemed bad and will be
|
||||
written as body */
|
||||
int headerline; /* counts header lines to better track the
|
||||
@@ -350,7 +359,7 @@ struct Curl_transfer_keeper {
|
||||
char *end_ptr; /* within buf */
|
||||
char *p; /* within headerbuff */
|
||||
bool content_range; /* set TRUE if Content-Range: was found */
|
||||
curl_off_t offset; /* possible resume offset read from the
|
||||
curl_off_t offset; /* possible resume offset read from the
|
||||
Content-Range: header */
|
||||
int httpcode; /* error code from the 'HTTP/1.? XXX' line */
|
||||
int httpversion; /* the HTTP version*10 */
|
||||
@@ -374,7 +383,6 @@ struct Curl_transfer_keeper {
|
||||
z_stream z; /* State structure for zlib. */
|
||||
#endif
|
||||
|
||||
/* for the low speed checks: */
|
||||
time_t timeofdoc;
|
||||
long bodywrites;
|
||||
|
||||
@@ -601,6 +609,8 @@ struct connectdata {
|
||||
/* data used for the asynch name resolve callback */
|
||||
struct Curl_async async;
|
||||
#endif
|
||||
struct connectdata *sec_conn; /* secondary connection for 3rd party
|
||||
transfer */
|
||||
};
|
||||
|
||||
/* The end of connectdata. */
|
||||
@@ -845,7 +855,11 @@ struct UserDefined {
|
||||
bool crlf; /* convert crlf on ftp upload(?) */
|
||||
struct curl_slist *quote; /* after connection is established */
|
||||
struct curl_slist *postquote; /* after the transfer */
|
||||
struct curl_slist *prequote; /* before the transfer, after type (Wesley Laxton)*/
|
||||
struct curl_slist *prequote; /* before the transfer, after type */
|
||||
struct curl_slist *source_prequote; /* in 3rd party transfer mode - before
|
||||
the transfer on source host */
|
||||
struct curl_slist *source_postquote; /* in 3rd party transfer mode - after
|
||||
the transfer on source host */
|
||||
struct curl_slist *telnet_options; /* linked list of telnet options */
|
||||
curl_TimeCond timecondition; /* kind of time/date comparison */
|
||||
time_t timevalue; /* what time to compare with */
|
||||
@@ -874,10 +888,17 @@ struct UserDefined {
|
||||
|
||||
curl_off_t max_filesize; /* Maximum file size to download */
|
||||
|
||||
char *source_host; /* for 3rd party transfer */
|
||||
char *source_port; /* for 3rd party transfer */
|
||||
char *source_userpwd; /* for 3rd party transfer */
|
||||
char *source_path; /* for 3rd party transfer */
|
||||
curl_pasv_side pasvHost; /* for 3rd party transfer indicates passive host */
|
||||
|
||||
/* Here follows boolean settings that define how to behave during
|
||||
this session. They are STATIC, set by libcurl users or at least initially
|
||||
and they don't change during operations. */
|
||||
|
||||
bool printhost; /* printing host name in debug info */
|
||||
bool get_filetime;
|
||||
bool tunnel_thru_httpproxy;
|
||||
bool ftp_append;
|
||||
|
@@ -1,7 +1,35 @@
|
||||
# fetch libcurl version number from input file and write them to STDOUT
|
||||
# ***************************************************************************
|
||||
# * _ _ ____ _
|
||||
# * Project ___| | | | _ \| |
|
||||
# * / __| | | | |_) | |
|
||||
# * | (__| |_| | _ <| |___
|
||||
# * \___|\___/|_| \_\_____|
|
||||
# *
|
||||
# * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# *
|
||||
# * This software is licensed as described in the file COPYING, which
|
||||
# * you should have received as part of this distribution. The terms
|
||||
# * are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
# *
|
||||
# * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# * copies of the Software, and permit persons to whom the Software is
|
||||
# * furnished to do so, under the terms of the COPYING file.
|
||||
# *
|
||||
# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# * KIND, either express or implied.
|
||||
# *
|
||||
# * $Id$
|
||||
# ***************************************************************************
|
||||
# awk script which fetches libcurl version number and string from input file
|
||||
# and writes them to STDOUT. Here you can get an awk version for Win32:
|
||||
# http://www.gknw.com/development/prgtools/awk.zip
|
||||
#
|
||||
BEGIN {
|
||||
while ((getline < ARGV[1]) > 0) {
|
||||
if (match ($0, /^#define LIBCURL_VERSION_MAJOR [^"]+/)) {
|
||||
if (match ($0, /^#define LIBCURL_VERSION "[^"]+"/)) {
|
||||
libcurl_ver_str = substr($3, 2, length($3)-2);
|
||||
}
|
||||
else if (match ($0, /^#define LIBCURL_VERSION_MAJOR [^"]+/)) {
|
||||
libcurl_ver_major = substr($3, 1, length($3));
|
||||
}
|
||||
else if (match ($0, /^#define LIBCURL_VERSION_MINOR [^"]+/)) {
|
||||
@@ -12,9 +40,6 @@ BEGIN {
|
||||
}
|
||||
}
|
||||
libcurl_ver = libcurl_ver_major "," libcurl_ver_minor "," libcurl_ver_patch;
|
||||
libcurl_ver_str = libcurl_ver_major "." libcurl_ver_minor "." libcurl_ver_patch;
|
||||
|
||||
print "LIBCURL_VERSION = " libcurl_ver "";
|
||||
print "LIBCURL_VERSION_STR = " libcurl_ver_str "";
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* MSK, 02/05/04, Hand edited for trail build on Alpha V7.3, DEC C 6.5-003 */
|
||||
/* MSK, 03/09/04, Seems to work for all platforms I've built on so far. */
|
||||
/* Added HAVE_SYS_IOCTL_H, IOCTL_3_ARGS and SIZEOF_CURL_OFF_T defines */
|
||||
/* MSK, 06/04/04, Added HAVE_INET_NTOP */
|
||||
|
||||
/* Define cpu-machine-OS */
|
||||
#ifdef __ALPHA
|
||||
@@ -258,3 +259,6 @@
|
||||
#else
|
||||
#define SIZEOF_CURL_OFF_T 8
|
||||
#endif
|
||||
|
||||
/* Somewhere around 7.12.0 HAVE_INET_NTOP was introduced. */
|
||||
#define HAVE_INET_NTOP 1
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* MSK, 02/05/04, Hand edited for trail build on Alpha V7.3, DEC C 6.5-003 */
|
||||
/* MSK, 03/09/04, Seems to work for all platforms I've built on so far. */
|
||||
/* Added HAVE_SYS_IOCTL_H, IOCTL_3_ARGS and SIZEOF_CURL_OFF_T defines */
|
||||
/* MSK, 06/04/04, Added HAVE_INET_NTOP */
|
||||
|
||||
/* Define cpu-machine-OS */
|
||||
#ifdef __ALPHA
|
||||
@@ -258,3 +259,6 @@
|
||||
#else
|
||||
#define SIZEOF_CURL_OFF_T 8
|
||||
#endif
|
||||
|
||||
/* Somewhere around 7.12.0 HAVE_INET_NTOP was introduced. */
|
||||
#define HAVE_INET_NTOP 1
|
||||
|
@@ -7,9 +7,9 @@
|
||||
;; First comes a setup that is ideal when you are only working with curl. Just
|
||||
;; select the next few lines, paste it into your .emacs and change the path to
|
||||
;; the tools folder. (If you are using more than one style. Look further down
|
||||
;; the this file.)
|
||||
;; this file.)
|
||||
|
||||
(load-file "<YOUR-PATH-TO-CURL>/tools/curl-style.el")
|
||||
(load-file "<YOUR-PATH-TO-CURL>/curl-style.el")
|
||||
(add-hook 'c-mode-common-hook 'curl-c-mode-common-hook)
|
||||
|
||||
;; If you are using more than one style in maybe more than one project the
|
||||
|
@@ -8,11 +8,13 @@
|
||||
#################################################################
|
||||
|
||||
# Edit the path below to point to the base of your Novell NDK.
|
||||
BASE = c:/novell
|
||||
INSTDIR = s:/libcurl
|
||||
ifndef NDKBASE
|
||||
NDKBASE = c:/novell
|
||||
endif
|
||||
INSTDIR = ..\curl-$(LIBCURL_VERSION_STR)-bin-nw
|
||||
|
||||
# Edit the path below to point to the base of your Zlib sources.
|
||||
ZLIB_PATH = ../../../cw/zlib-src-1.1.4
|
||||
#ZLIB_PATH = ../../zlib-1.2.1
|
||||
|
||||
# Edit the vars below to change NLM target settings.
|
||||
TARGET = curl
|
||||
@@ -24,6 +26,8 @@ STACK = 64000
|
||||
SCREEN = $(TARGET) commandline utility
|
||||
MODULES = libcurl.nlm
|
||||
IMPORTS = @../lib/libcurl.imp
|
||||
# Comment the line below if you dont want to load protected automatically.
|
||||
LDRING = 3
|
||||
|
||||
# Edit the var below to point to your lib architecture.
|
||||
ifndef LIBARCH
|
||||
@@ -42,7 +46,7 @@ else
|
||||
OBJDIR = debug
|
||||
endif
|
||||
|
||||
# Include the version info retrieved from jk_version.h
|
||||
# Include the version info retrieved from curlver.h
|
||||
-include $(OBJDIR)/version.inc
|
||||
|
||||
# The following line defines your compiler.
|
||||
@@ -51,52 +55,51 @@ ifdef METROWERKS
|
||||
else
|
||||
CC = gcc
|
||||
endif
|
||||
CP = cp -afv
|
||||
# RM = rm -f
|
||||
# CP = cp -fv
|
||||
# if you want to mark the target as MTSAFE you will need a tool for
|
||||
# generating the xdc data for the linker; here's a minimal tool:
|
||||
# http://www.gknw.de/development/prgtools/mkxdc.zip
|
||||
# http://www.gknw.com/development/prgtools/mkxdc.zip
|
||||
MPKXDC = mkxdc
|
||||
|
||||
# Global flags for all compilers
|
||||
CFLAGS = $(OPT) -D$(DB) -DNETWARE -nostdinc
|
||||
CFLAGS += -DUSE_MANUAL
|
||||
#CFLAGS += -DHAVE_LIBZ
|
||||
|
||||
ifeq ($(CC),mwccnlm)
|
||||
LD = mwldnlm
|
||||
LDFLAGS = -nostdlib $(PRELUDE) $(OBJDIR)/*.o -o $(OBJDIR)/$(TARGET).nlm -commandfile
|
||||
CFLAGS += -gccinc -inline off -opt nointrinsics
|
||||
CFLAGS += -gccinc -inline off -opt nointrinsics -proc 586
|
||||
CFLAGS += -relax_pointers
|
||||
#CFLAGS += -w on
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
PRELUDE = $(SDK_LIBC)/imports/libcpre.o
|
||||
CFLAGS += -align 4 -inst mmx -proc 686
|
||||
CFLAGS += -align 4
|
||||
CFLAGS += -D_POSIX_SOURCE
|
||||
# CFLAGS += -D__ANSIC__
|
||||
else
|
||||
PRELUDE = "$(METROWERKS)/Novell Support/libraries/runtime/prelude.obj"
|
||||
# CFLAGS += -include "$(METROWERKS)/Novell Support/headers/nlm_prefix.h"
|
||||
CFLAGS += -align 1 -proc 586
|
||||
CFLAGS += -align 1
|
||||
endif
|
||||
else
|
||||
LD = nlmconv
|
||||
LDFLAGS = -T
|
||||
CFLAGS += -fno-builtin -fpack-struct -fpcc-struct-return
|
||||
CFLAGS += -Wall #-Wno-main # -pedantic
|
||||
CFLAGS += -Wall # -pedantic
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
PRELUDE = $(SDK_LIBC)/imports/libcpre.gcc.o
|
||||
CFLAGS += -D_POSIX_SOURCE
|
||||
# CFLAGS += -D__ANSIC__
|
||||
else
|
||||
PRELUDE = $(SDK_CLIB)/imports/clibpre.gcc.o
|
||||
CFLAGS += -include $(BASE)/nlmconv/genlm.h
|
||||
CFLAGS += -include $(NDKBASE)/nlmconv/genlm.h
|
||||
endif
|
||||
endif
|
||||
|
||||
LDLIBS =
|
||||
|
||||
NDK_ROOT = $(BASE)/ndk
|
||||
NDK_ROOT = $(NDKBASE)/ndk
|
||||
SDK_CLIB = $(NDK_ROOT)/nwsdk
|
||||
SDK_LIBC = $(NDK_ROOT)/libc
|
||||
SDK_LDAP = $(NDK_ROOT)/cldapsdk/netware
|
||||
@@ -104,26 +107,38 @@ CURL_INC = ../include
|
||||
CURL_LIB = ../lib
|
||||
|
||||
INCLUDES = -I$(CURL_INC) -I$(CURL_LIB)
|
||||
INCLUDES += -I$(ZLIB_PATH)
|
||||
|
||||
ifdef ZLIB_PATH
|
||||
INCLUDES += -I$(ZLIB_PATH)
|
||||
CFLAGS += -DHAVE_ZLIB_H -DHAVE_LIBZ
|
||||
IMPORTS+ = @$(ZLIB_PATH)/nw/zlib.imp
|
||||
MODULES+ = libz.nlm
|
||||
endif
|
||||
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
INCLUDES += -I$(SDK_LIBC)/include -I$(SDK_LIBC)/include/nks
|
||||
INCLUDES += -I$(SDK_LIBC)/include/winsock
|
||||
INCLUDES += -I$(SDK_LDAP)/libc/inc
|
||||
# INCLUDES += -I$(SDK_LDAP)/libc/inc
|
||||
else
|
||||
INCLUDES += -I$(SDK_CLIB)/include/nlm -I$(SDK_CLIB)/include
|
||||
INCLUDES += -I$(SDK_LDAP)/clib/inc
|
||||
# INCLUDES += -I$(SDK_LDAP)/clib/inc
|
||||
CFLAGS += -DNETDB_USE_INTERNET
|
||||
endif
|
||||
CFLAGS += $(INCLUDES)
|
||||
|
||||
ifeq ($(MTSAFE),YES)
|
||||
XDCOPT = -n
|
||||
endif
|
||||
ifeq ($(MTSAFE),NO)
|
||||
XDCOPT = -u
|
||||
endif
|
||||
ifdef XDCOPT
|
||||
XDCDATA = $(OBJDIR)/$(TARGET).xdc
|
||||
endif
|
||||
|
||||
ifeq ($(OSTYPE),linux)
|
||||
DL = '
|
||||
-include $(BASE)/nlmconv/ncpfs.inc
|
||||
#-include $(NDKBASE)/nlmconv/ncpfs.inc
|
||||
endif
|
||||
|
||||
OBJS = \
|
||||
@@ -132,31 +147,34 @@ OBJS = \
|
||||
$(OBJDIR)/urlglob.o \
|
||||
$(OBJDIR)/writeout.o \
|
||||
$(OBJDIR)/getpass.o \
|
||||
$(OBJDIR)/homedir.o
|
||||
$(OBJDIR)/homedir.o \
|
||||
$(OBJDIR)/timeval.o
|
||||
|
||||
vpath %.c ../lib
|
||||
|
||||
all: $(OBJDIR) $(OBJDIR)/version.inc $(OBJDIR)/$(TARGET).nlm
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@echo Compiling $<
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
# @echo Compiling $<
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/version.inc: $(CURL_INC)/curl/curl.h $(OBJDIR)
|
||||
$(OBJDIR)/version.inc: $(CURL_INC)/curl/curlver.h $(OBJDIR)
|
||||
@echo Creating $@
|
||||
@awk -f ../packages/netware/get_ver.awk $< > $@
|
||||
@awk -f ../packages/NetWare/get_ver.awk $< > $@
|
||||
|
||||
dist: all
|
||||
-$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(TARGET).map $(OBJDIR)/$(TARGET).ncv
|
||||
-$(RM) $(OBJDIR)/$(TARGET).def $(OBJDIR)/version.inc $(XDCDATA)
|
||||
# -$(CP) ../changes.txt $(OBJDIR)/
|
||||
|
||||
install: all
|
||||
@[ -d $(INSTDIR) ] || mkdir $(INSTDIR)
|
||||
install: $(INSTDIR) all
|
||||
@$(CP) $(TARGET).nlm $(INSTDIR)
|
||||
|
||||
clean:
|
||||
-$(RM) -r $(OBJDIR)
|
||||
|
||||
$(INSTDIR):
|
||||
@mkdir $(INSTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
@mkdir $(OBJDIR)
|
||||
|
||||
@@ -195,6 +213,12 @@ endif
|
||||
ifdef XDCDATA
|
||||
@echo $(DL)xdcdata $(XDCDATA)$(DL) >> $@
|
||||
endif
|
||||
ifeq ($(LDRING),0)
|
||||
@echo $(DL)flag_on 16$(DL) >> $@
|
||||
endif
|
||||
ifeq ($(LDRING),3)
|
||||
@echo $(DL)flag_on 512$(DL) >> $@
|
||||
endif
|
||||
ifeq ($(LIBARCH),CLIB)
|
||||
@echo $(DL)start _Prelude$(DL) >> $@
|
||||
@echo $(DL)exit _Stop$(DL) >> $@
|
||||
@@ -202,25 +226,21 @@ ifeq ($(LIBARCH),CLIB)
|
||||
@echo $(DL)import @$(SDK_CLIB)/imports/threads.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_CLIB)/imports/nlmlib.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_CLIB)/imports/socklib.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapsdk.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapssl.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapx.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapsdk.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapssl.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/clib/imports/ldapx.imp$(DL) >> $@
|
||||
@echo $(DL)module clib$(DL) >> $@
|
||||
else
|
||||
ifeq ($(LD),nlmconv)
|
||||
@echo $(DL)flag_on 64$(DL) >> $@
|
||||
else
|
||||
@echo $(DL)autounload$(DL) >> $@
|
||||
endif
|
||||
@echo $(DL)pseudopreemption$(DL) >> $@
|
||||
@echo $(DL)start _LibCPrelude$(DL) >> $@
|
||||
@echo $(DL)exit _LibCPostlude$(DL) >> $@
|
||||
@echo $(DL)check _LibCCheckUnload$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LIBC)/imports/libc.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LIBC)/imports/netware.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapsdk.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapssl.imp$(DL) >> $@
|
||||
@echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapx.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapsdk.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapssl.imp$(DL) >> $@
|
||||
# @echo $(DL)import @$(SDK_LDAP)/libc/imports/lldapx.imp$(DL) >> $@
|
||||
@echo $(DL)module libc$(DL) >> $@
|
||||
endif
|
||||
ifdef MODULES
|
||||
@@ -238,3 +258,8 @@ ifeq ($(LD),nlmconv)
|
||||
@echo $(DL)output $(TARGET).nlm$(DL) >> $@
|
||||
endif
|
||||
|
||||
hugehelp.c: hugehelp.c.cvs
|
||||
@echo Creating $@
|
||||
@$(CP) $< $@
|
||||
|
||||
|
||||
|
@@ -185,10 +185,6 @@
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
#undef HAVE_LIBSSL
|
||||
|
||||
/* If zlib is available */
|
||||
#undef HAVE_LIBZ
|
||||
//#define HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
@@ -399,14 +395,17 @@
|
||||
/* Define to 1 if you have the <x509.h> header file. */
|
||||
#undef HAVE_X509_H
|
||||
|
||||
/* if you have the zlib.h header file */
|
||||
#define HAVE_ZLIB_H 1
|
||||
/* if you have the zlib.h header file - set from Makefile */
|
||||
/* #undef HAVE_ZLIB_H */
|
||||
|
||||
/* If zlib is available - set from Makefile */
|
||||
/* #undef HAVE_LIBZ */
|
||||
|
||||
/* need REENTRANT defined */
|
||||
#undef NEED_REENTRANT
|
||||
|
||||
/* cpu-machine-OS */
|
||||
#define OS "i386-pc-NetWare"
|
||||
#define OS "i586-pc-NetWare"
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
@@ -45,12 +45,22 @@
|
||||
#include descrip
|
||||
#include starlet
|
||||
#include iodef
|
||||
#include iosbdef
|
||||
/* #include iosbdef */
|
||||
char *getpass_r(const char *prompt, char *buffer, size_t buflen)
|
||||
{
|
||||
long sts;
|
||||
short chan;
|
||||
struct _iosb iosb;
|
||||
|
||||
/* MSK, 23-JAN-2004, iosbdef.h wasn't in VAX V7.2 or CC 6.4 */
|
||||
/* distribution so I created this. May revert back later to */
|
||||
/* struct _iosb iosb; */
|
||||
struct _iosb
|
||||
{
|
||||
short int iosb$w_status; /* status */
|
||||
short int iosb$w_bcnt; /* byte count */
|
||||
int unused; /* unused */
|
||||
} iosb;
|
||||
|
||||
$DESCRIPTOR(ttdesc, "TT");
|
||||
|
||||
buffer[0]='\0';
|
||||
|
@@ -2572,7 +2572,6 @@ int my_trace(CURL *handle, curl_infotype type,
|
||||
struct Configurable *config = (struct Configurable *)userp;
|
||||
FILE *output=config->errors;
|
||||
const char *text;
|
||||
|
||||
(void)handle; /* prevent compiler warning */
|
||||
|
||||
if(!config->trace_stream) {
|
||||
@@ -2606,6 +2605,12 @@ int my_trace(CURL *handle, curl_infotype type,
|
||||
case CURLINFO_DATA_IN:
|
||||
text = "<= Recv data";
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
text = "<= Recv SSL data";
|
||||
break;
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
text = "<= Send SSL data";
|
||||
break;
|
||||
}
|
||||
|
||||
dump(text, output, data, size, config->trace_ascii);
|
||||
@@ -2904,7 +2909,7 @@ operate(struct Configurable *config, int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* loop through the list of given URLs */
|
||||
while(urlnode && !res) {
|
||||
while(urlnode) {
|
||||
char *dourl;
|
||||
|
||||
/* get the full URL (it might be NULL) */
|
||||
|
304
testcurl.sh
304
testcurl.sh
@@ -1,304 +0,0 @@
|
||||
#!/bin/sh
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# $Id$
|
||||
###########################################################################
|
||||
|
||||
###########################
|
||||
# What is This Script?
|
||||
###########################
|
||||
|
||||
# testcurl.sh is the master script to use for automatic testing of CVS-curl.
|
||||
# This is written for the purpose of being run from a crontab job or similar
|
||||
# at a regular interval. The output will be suitable to be mailed automaticly
|
||||
# to "curl-autocompile@haxx.se" to be dealt with automatically. The most
|
||||
# current build status (with a resonable backlog) will be published on the
|
||||
# curl site, at http://curl.haxx.se/auto/
|
||||
|
||||
# USAGE:
|
||||
# testcurl.sh [curl-daily-name] > output
|
||||
|
||||
# Updated:
|
||||
# v1.1 6-Nov-03 - to take an optional parameter, the name of a daily-build
|
||||
# directory. If present, build from that directory, otherwise
|
||||
# perform a normal CVS build.
|
||||
|
||||
# version of this script
|
||||
version='$Revision$'
|
||||
fixed=0
|
||||
|
||||
# Determine if we're running from CVS or a canned copy of curl
|
||||
if [ "$#" -ge "1" -a "$1" ]; then
|
||||
CURLDIR=$1
|
||||
CVS=0
|
||||
else
|
||||
CURLDIR="curl"
|
||||
CVS=1
|
||||
fi
|
||||
|
||||
LANG="C"
|
||||
|
||||
export LANG
|
||||
|
||||
log() {
|
||||
text=$1
|
||||
if test -n "$text"; then
|
||||
echo "testcurl: $text"
|
||||
fi
|
||||
}
|
||||
|
||||
die(){
|
||||
text=$1
|
||||
log "$text"
|
||||
cd $pwd # cd back to the original root dir
|
||||
|
||||
if test -n "$pwd/$build"; then
|
||||
# we have a build directory name, remove the dir
|
||||
log "removing the $build dir"
|
||||
rm -rf "$pwd/$build"
|
||||
fi
|
||||
if test -r "$buildlog"; then
|
||||
# we have a build log output file left, remove it
|
||||
log "removing the $buildlogname file"
|
||||
rm -rf "$buildlog"
|
||||
fi
|
||||
log "ENDING HERE" # last line logged!
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -f setup ]; then
|
||||
. "./setup"
|
||||
infixed="$fixed"
|
||||
else
|
||||
infixed=0 # so that "additional args to configure" works properly first time...
|
||||
fi
|
||||
|
||||
if [ -z "$name" ]; then
|
||||
echo "please enter your name"
|
||||
read name
|
||||
fixed="1"
|
||||
fi
|
||||
|
||||
if [ -z "$email" ]; then
|
||||
echo "please enter your contact email address"
|
||||
read email
|
||||
fixed="2"
|
||||
fi
|
||||
|
||||
if [ -z "$desc" ]; then
|
||||
echo "please enter a one line system description"
|
||||
read desc
|
||||
fixed="3"
|
||||
fi
|
||||
|
||||
if [ -z "$confopts" ]; then
|
||||
if [ $infixed -lt 4 ]; then
|
||||
echo "please enter your additional arguments to configure"
|
||||
echo "examples: --with-ssl --enable-debug --enable-ipv6 --with-krb4"
|
||||
read confopts
|
||||
fixed="4"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ "$fixed" -gt "0" ]; then
|
||||
echo "name='$name'" > setup
|
||||
echo "email='$email'" >> setup
|
||||
echo "desc='$desc'" >> setup
|
||||
echo "confopts='$confopts'" >> setup
|
||||
echo "fixed='$fixed'" >> setup
|
||||
fi
|
||||
|
||||
log "STARTING HERE" # first line logged
|
||||
log "NAME = $name"
|
||||
log "EMAIL = $email"
|
||||
log "DESC = $desc"
|
||||
log "CONFOPTS = $confopts"
|
||||
log "CFLAGS = $CFLAGS"
|
||||
log "CC = $CC"
|
||||
log "version = $version"
|
||||
log "date = `date -u`"
|
||||
log "testscript = obsolete shell version, use tests/testcurl.pl instead!"
|
||||
|
||||
# Make $pwd to become the path without newline. We'll use that in order to cut
|
||||
# off that path from all possible logs and error messages etc.
|
||||
ipwd=`pwd`
|
||||
pwd=`echo $ipwd | sed -e 's/$//g'`
|
||||
|
||||
if [ -d "$CURLDIR" ]; then
|
||||
if [ $CVS -eq 1 -a -d $CURLDIR/CVS ]; then
|
||||
log "curl is verified to be a fine source dir"
|
||||
# remove the generated sources to force them to be re-generated each
|
||||
# time we run this test
|
||||
rm -f $CURLDIR/lib/getdate.c
|
||||
rm -f $CURLDIR/src/hugehelp.c
|
||||
elif [ $CVS -eq 0 -a -f $CURLDIR/testcurl.sh ]; then
|
||||
log "curl is verified to be a fine daily source dir"
|
||||
else
|
||||
die "curl is not a daily source dir or checked out from CVS!"
|
||||
fi
|
||||
fi
|
||||
build="build-$$"
|
||||
buildlogname="buildlog-$$"
|
||||
buildlog="$pwd/$buildlogname"
|
||||
|
||||
# remove any previous left-overs
|
||||
rm -rf build-*
|
||||
rm -rf buildlog-*
|
||||
|
||||
# this is to remove old build logs that ended up in the wrong dir
|
||||
rm -rf $CURLDIR/buildlog-*
|
||||
|
||||
# create a dir to build in
|
||||
mkdir $build
|
||||
|
||||
if [ -d $build ]; then
|
||||
log "build dir $build was created fine"
|
||||
else
|
||||
die "failed to create dir $build"
|
||||
fi
|
||||
|
||||
# get in the curl source tree root
|
||||
cd $CURLDIR
|
||||
|
||||
# Do the CVS thing, or not...
|
||||
if [ $CVS -eq 1 ]; then
|
||||
|
||||
# this is a temporary fix to make things work again, remove later
|
||||
log "remove ares/aclocal.m4"
|
||||
rm -f ares/aclocal.m4
|
||||
|
||||
log "update from CVS"
|
||||
|
||||
cvsup() {
|
||||
# update quietly to the latest CVS
|
||||
log "run cvs up"
|
||||
cvs -Q up -dP 2>&1
|
||||
|
||||
cvsstat=$?
|
||||
|
||||
# return (1 - RETURNVALUE) so that errors return 0 while goodness
|
||||
# returns 1
|
||||
return `expr 1 - $cvsstat`
|
||||
}
|
||||
|
||||
att="0"
|
||||
while cvsup; do
|
||||
att=`expr $att + 1`
|
||||
log "failed CVS update attempt number $att."
|
||||
if [ $att -gt 10 ]; then
|
||||
cvsstat="111"
|
||||
break # get out of the loop
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
if [ "$cvsstat" -ne "0" ]; then
|
||||
die "failed to update from CVS ($cvsstat), exiting"
|
||||
fi
|
||||
|
||||
# remove possible left-overs from the past
|
||||
rm -f configure
|
||||
rm -rf autom4te.cache
|
||||
|
||||
# generate the build files
|
||||
log "invoke buildconf, but filter off the silly aclocal warnings"
|
||||
./buildconf 2>&1 | grep -v "warning: underquoted definition of" | tee $buildlog
|
||||
|
||||
if { grep "^buildconf: OK" $buildlog >/dev/null 2>&1; } then
|
||||
log "buildconf was successful"
|
||||
else
|
||||
die "buildconf was NOT successful"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ -f configure ]; then
|
||||
log "configure created"
|
||||
else
|
||||
die "no configure created"
|
||||
fi
|
||||
|
||||
# change to build dir
|
||||
cd "../$build"
|
||||
|
||||
# run configure script
|
||||
../$CURLDIR/configure $confopts 2>&1
|
||||
|
||||
if [ -f lib/Makefile ]; then
|
||||
log "configure seems to have finished fine"
|
||||
else
|
||||
die "configure didn't work"
|
||||
fi
|
||||
|
||||
log "display lib/config.h"
|
||||
grep "^ *#" lib/config.h
|
||||
|
||||
log "display src/config.h"
|
||||
grep "^ *#" src/config.h
|
||||
|
||||
if { grep "define USE_ARES" lib/config.h; } then
|
||||
log "setup to build ares"
|
||||
|
||||
log "build ares"
|
||||
cd ares
|
||||
make 2>&1 | sed -e "s:$pwd::g"
|
||||
|
||||
if [ -f libcares.a ]; then
|
||||
log "ares is now built successfully"
|
||||
else
|
||||
log "ares build failed"
|
||||
fi
|
||||
|
||||
# cd back to the curl build dir
|
||||
cd ..
|
||||
fi
|
||||
|
||||
log "run make"
|
||||
make -i 2>&1 | sed -e "s:$pwd::g"
|
||||
|
||||
if [ -f src/curl ]; then
|
||||
log "src/curl was created fine"
|
||||
else
|
||||
die "src/curl was not created"
|
||||
fi
|
||||
|
||||
log "display curl --version output"
|
||||
|
||||
./src/curl --version
|
||||
|
||||
log "run make test-full"
|
||||
make test-full 2>&1 | sed -e "s:$pwd::g" | tee $buildlog
|
||||
|
||||
if { grep "^TEST" $buildlog >/dev/null 2>&1; } then
|
||||
log "tests were run"
|
||||
else
|
||||
die "test suite failure"
|
||||
fi
|
||||
|
||||
if { grep "^TESTFAIL:" $buildlog >/dev/null 2>&1; } then
|
||||
log "the tests were not successful"
|
||||
else
|
||||
log "the tests were successful!"
|
||||
fi
|
||||
|
||||
# die to cleanup
|
||||
die "ending nicely"
|
@@ -33,14 +33,26 @@ CLEANFILES = .http.pid .https.pid .ftp.pid .ftps.pid
|
||||
curl:
|
||||
@cd $(top_builddir) && $(MAKE)
|
||||
|
||||
if CROSSCOMPILING
|
||||
TEST = @echo "NOTICE: we can't run the tests when cross-compiling!"
|
||||
TEST_Q = $(TEST)
|
||||
TEST_F = $(TEST)
|
||||
TEST_T = $(TEST)
|
||||
else # if not cross-compiling:
|
||||
TEST = srcdir=$(srcdir) $(PERL) $(PERLFLAGS) $(srcdir)/runtests.pl
|
||||
TEST_Q = $(TEST) -s -a
|
||||
TEST_F = $(TEST) -a -p
|
||||
TEST_T = $(TEST) -t
|
||||
endif
|
||||
|
||||
test: all
|
||||
srcdir=$(srcdir) $(PERL) $(PERLFLAGS) $(srcdir)/runtests.pl
|
||||
$(TEST)
|
||||
|
||||
quiet-test: all
|
||||
srcdir=$(srcdir) $(PERL) $(PERLFLAGS) $(srcdir)/runtests.pl -s -a
|
||||
$(TEST_Q)
|
||||
|
||||
full-test: all
|
||||
srcdir=$(srcdir) $(PERL) $(PERLFLAGS) $(srcdir)/runtests.pl -a -p
|
||||
$(TEST_F)
|
||||
|
||||
torture-test: all
|
||||
srcdir=$(srcdir) $(PERL) $(PERLFLAGS) $(srcdir)/runtests.pl -t
|
||||
$(TEST_T)
|
||||
|
@@ -24,7 +24,8 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
|
||||
test150 test151 test152 test153 test154 test155 test156 test157 \
|
||||
test158 test159 test511 test160 test161 test162 test163 test164 \
|
||||
test512 test165 test166 test167 test168 test169 test170 test171 \
|
||||
test172 test204 test205
|
||||
test172 test204 test205 test173 test174 test175 test176 test177 \
|
||||
test513
|
||||
|
||||
# The following tests have been removed from the dist since they no longer
|
||||
# work. We need to fix the test suite's FTPS server first, then bring them
|
||||
|
@@ -64,14 +64,14 @@ Pragma: no-cache
|
||||
Accept: */*
|
||||
|
||||
GET http://data.from.server.requiring.digest.hohoho.com/168 HTTP/1.1
|
||||
Proxy-Authorization: Digest username="digest", realm="weirdorealm", nonce="12345", uri="/168", response="4e79e4fc104ef1f16ab4567e1ad4dede"
|
||||
Proxy-Authorization: Digest username="foo", realm="weirdorealm", nonce="12345", uri="/168", response="fb8608e00ad9239a3dedb14bc8575976"
|
||||
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b zlib/1.1.4 c-ares/1.2.0 libidn/0.4.3
|
||||
Host: data.from.server.requiring.digest.hohoho.com
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
|
||||
GET http://data.from.server.requiring.digest.hohoho.com/168 HTTP/1.1
|
||||
Proxy-Authorization: Digest username="digest", realm="weirdorealm", nonce="12345", uri="/168", response="4e79e4fc104ef1f16ab4567e1ad4dede"
|
||||
Proxy-Authorization: Digest username="foo", realm="weirdorealm", nonce="12345", uri="/168", response="fb8608e00ad9239a3dedb14bc8575976"
|
||||
Authorization: Digest username="digest", realm="realmweirdo", nonce="123456", uri="/168", response="ca87f2d768a231e2d637a55698d5c416"
|
||||
User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) libcurl/7.12.0-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.3
|
||||
Host: data.from.server.requiring.digest.hohoho.com
|
||||
|
71
tests/data/test173
Normal file
71
tests/data/test173
Normal file
@@ -0,0 +1,71 @@
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 OK swsclose
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
|
||||
blablabla
|
||||
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP RFC1867-formpost a file from stdin with "faked" filename
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HOSTPORT/we/want/173 -F field1=contents1 -F "fileupload=@-;filename=/dev/null"
|
||||
</command>
|
||||
|
||||
<stdin>
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
line4
|
||||
line5
|
||||
line6
|
||||
line7
|
||||
line8
|
||||
</stdin>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^(User-Agent:|Content-Type: multipart/form-data;|------------).*
|
||||
</strip>
|
||||
<protocol>
|
||||
POST /we/want/173 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
Content-Length: 359
|
||||
Expect: 100-continue
|
||||
Content-Type: multipart/form-data; boundary=----------------------------5dbea401cd8c
|
||||
|
||||
------------------------------5dbea401cd8c
|
||||
Content-Disposition: form-data; name="field1"
|
||||
|
||||
contents1
|
||||
------------------------------5dbea401cd8c
|
||||
Content-Disposition: form-data; name="fileupload"; filename="/dev/null"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
line4
|
||||
line5
|
||||
line6
|
||||
line7
|
||||
line8
|
||||
|
||||
------------------------------5dbea401cd8c--
|
||||
</protocol>
|
||||
</verify>
|
71
tests/data/test174
Normal file
71
tests/data/test174
Normal file
@@ -0,0 +1,71 @@
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 beng swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Authentication-Info: Passport1.4 tname=MSPAuth,tname=MSPProf,tname=MSPConsent,tname=MSPSecAuth
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
This is not the real page
|
||||
</data>
|
||||
|
||||
<data1>
|
||||
HTTP/1.1 200 moo swsclose
|
||||
Server: Microsoft-IIS/6.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
content for you
|
||||
</data1>
|
||||
|
||||
<datacheck>
|
||||
HTTP/1.1 200 beng swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Authentication-Info: Passport1.4 tname=MSPAuth,tname=MSPProf,tname=MSPConsent,tname=MSPSecAuth
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
HTTP/1.1 200 moo swsclose
|
||||
Server: Microsoft-IIS/6.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
content for you
|
||||
</datacheck>
|
||||
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
#
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP POST --anyauth to server not requiring any auth at all
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HOSTPORT/174 -u testuser:testpass --anyauth -d "junkelijunk"
|
||||
</command>
|
||||
</test>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol nonewline=yes>
|
||||
HEAD /174 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
|
||||
POST /174 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
Content-Length: 11
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
junkelijunk
|
||||
</protocol>
|
||||
</verify>
|
71
tests/data/test175
Normal file
71
tests/data/test175
Normal file
@@ -0,0 +1,71 @@
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 beng swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Authentication-Info: Passport1.4 tname=MSPAuth,tname=MSPProf,tname=MSPConsent,tname=MSPSecAuth
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
This is not the real page
|
||||
</data>
|
||||
|
||||
<data1>
|
||||
HTTP/1.1 200 moo swsclose
|
||||
Server: Microsoft-IIS/6.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
content for you
|
||||
</data1>
|
||||
|
||||
<datacheck>
|
||||
HTTP/1.1 200 beng swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Authentication-Info: Passport1.4 tname=MSPAuth,tname=MSPProf,tname=MSPConsent,tname=MSPSecAuth
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
HTTP/1.1 200 moo swsclose
|
||||
Server: Microsoft-IIS/6.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
content for you
|
||||
</datacheck>
|
||||
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
#
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP POST --digest to server not requiring any auth at all
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HOSTPORT/175 -u auser:apasswd --digest -d "junkelijunk"
|
||||
</command>
|
||||
</test>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol nonewline=yes>
|
||||
HEAD /175 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
|
||||
POST /175 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
Content-Length: 11
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
junkelijunk
|
||||
</protocol>
|
||||
</verify>
|
76
tests/data/test176
Normal file
76
tests/data/test176
Normal file
@@ -0,0 +1,76 @@
|
||||
# Server-side
|
||||
<reply>
|
||||
# the first request has NTLM type-1 included, and then the 1001 is returned
|
||||
<data1001>
|
||||
HTTP/1.1 200 beng swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Authentication-Info: Passport1.4 tname=MSPAuth,tname=MSPProf,tname=MSPConsent,tname=MSPSecAuth
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
</data1001>
|
||||
|
||||
# the second request should be auth-less and then this is returned.
|
||||
<data>
|
||||
HTTP/1.1 200 moo swsclose
|
||||
Server: Microsoft-IIS/6.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
content for you
|
||||
</data>
|
||||
|
||||
<datacheck>
|
||||
HTTP/1.1 200 beng swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Authentication-Info: Passport1.4 tname=MSPAuth,tname=MSPProf,tname=MSPConsent,tname=MSPSecAuth
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
HTTP/1.1 200 moo swsclose
|
||||
Server: Microsoft-IIS/6.0
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
content for you
|
||||
</datacheck>
|
||||
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
# require SSL since we need that for NTLM
|
||||
<features>
|
||||
SSL
|
||||
</features>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP POST --ntlm to server not requiring any auth at all
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HOSTPORT/176 -u auser:apasswd --ntlm -d "junkelijunk"
|
||||
</command>
|
||||
</test>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol nonewline=yes>
|
||||
HEAD /176 HTTP/1.1
|
||||
Authorization: NTLM TlRMTVNTUAABAAAAAgIAAAAAAAAgAAAAAAAAACAAAAA=
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
|
||||
POST /176 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
Content-Length: 11
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
junkelijunk
|
||||
</protocol>
|
||||
</verify>
|
39
tests/data/test177
Normal file
39
tests/data/test177
Normal file
@@ -0,0 +1,39 @@
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 302 *MOVED* swsclose swsbounce
|
||||
Server: Microsoft-IIS/6.0
|
||||
Location: /mooooo/177
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
#
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP POST --digest to server doing a 302-location response
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HOSTPORT/177 -u auser:apasswd --digest -d "junkelijunk"
|
||||
</command>
|
||||
</test>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
HEAD /177 HTTP/1.1
|
||||
User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
File diff suppressed because one or more lines are too long
40
tests/data/test513
Normal file
40
tests/data/test513
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
# tool is what to use instead of 'curl'
|
||||
<tool>
|
||||
lib513
|
||||
</tool>
|
||||
|
||||
<name>
|
||||
send HTTP POST using read callback that returns CURL_READFUNC_ABORT
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HOSTPORT/513
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
POST /513 HTTP/1.1
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
Accept: */*
|
||||
Content-Length: 1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
</protocol>
|
||||
# 42 - aborted by callback
|
||||
<errorcode>
|
||||
42
|
||||
</errorcode>
|
||||
</verify>
|
@@ -43,8 +43,7 @@ sub logmsg {
|
||||
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
|
||||
localtime(time);
|
||||
open(FTPLOG, ">>log/ftpd.log");
|
||||
printf FTPLOG ("%02d:%02d:%02d (%d) ",
|
||||
$hour, $min, $sec, $$);
|
||||
printf FTPLOG ("%02d:%02d:%02d ", $hour, $min, $sec);
|
||||
print FTPLOG @_;
|
||||
close(FTPLOG);
|
||||
}
|
||||
@@ -67,6 +66,7 @@ my $verbose=0; # set to 1 for debugging
|
||||
my $retrweirdo=0;
|
||||
my $retrnosize=0;
|
||||
my $srcdir=".";
|
||||
my $nosave=0;
|
||||
|
||||
my $port = 8921; # just a default
|
||||
do {
|
||||
@@ -382,7 +382,10 @@ sub STOR_command {
|
||||
my $ulsize=0;
|
||||
while (defined($line = <SOCK>)) {
|
||||
$ulsize += length($line);
|
||||
print FILE $line;
|
||||
print FILE $line if(!$nosave);
|
||||
}
|
||||
if($nosave) {
|
||||
print FILE "$ulsize bytes would've been stored here\n";
|
||||
}
|
||||
close(FILE);
|
||||
close_dataconn();
|
||||
@@ -497,6 +500,9 @@ my %customcount;
|
||||
my %delayreply;
|
||||
sub customize {
|
||||
undef %customreply;
|
||||
|
||||
$nosave = 0; # default is to save as normal
|
||||
|
||||
open(CUSTOM, "<log/ftpserver.cmd") ||
|
||||
return 1;
|
||||
|
||||
@@ -505,23 +511,32 @@ sub customize {
|
||||
while(<CUSTOM>) {
|
||||
if($_ =~ /REPLY ([A-Z]+) (.*)/) {
|
||||
$customreply{$1}=$2;
|
||||
logmsg "FTPD: set custom reply for $1\n";
|
||||
}
|
||||
if($_ =~ /COUNT ([A-Z]+) (.*)/) {
|
||||
# we blank the customreply for this command when having
|
||||
# been used this number of times
|
||||
$customcount{$1}=$2;
|
||||
logmsg "FTPD: blank custom reply for $1 after $2 uses\n";
|
||||
}
|
||||
elsif($_ =~ /DELAY ([A-Z]+) (\d*)/) {
|
||||
$delayreply{$1}=$2;
|
||||
logmsg "FTPD: delay reply for $1 with $2 seconds\n";
|
||||
}
|
||||
elsif($_ =~ /RETRWEIRDO/) {
|
||||
print "instructed to use RETRWEIRDO\n";
|
||||
logmsg "FTPD: instructed to use RETRWEIRDO\n";
|
||||
$retrweirdo=1;
|
||||
}
|
||||
elsif($_ =~ /RETRNOSIZE/) {
|
||||
print "instructed to use RETRNOSIZE\n";
|
||||
logmsg "FTPD: instructed to use RETRNOSIZE\n";
|
||||
$retrnosize=1;
|
||||
}
|
||||
elsif($_ =~ /NOSAVE/) {
|
||||
# don't actually store the file we upload - to be used when
|
||||
# uploading insanely huge amounts
|
||||
$nosave = 1;
|
||||
logmsg "FTPD: NOSAVE prevents saving of uploaded data\n";
|
||||
}
|
||||
}
|
||||
close(CUSTOM);
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ SUPPORTFILES = first.c test.h
|
||||
|
||||
# These are all libcurl test programs
|
||||
noinst_PROGRAMS = lib500 lib501 lib502 lib503 lib504 lib505 lib506 lib507 \
|
||||
lib508 lib509 lib510 lib511 lib512
|
||||
lib508 lib509 lib510 lib511 lib512 lib513
|
||||
|
||||
lib500_SOURCES = lib500.c $(SUPPORTFILES)
|
||||
lib500_LDADD = $(LIBDIR)/libcurl.la
|
||||
@@ -92,3 +92,7 @@ lib511_DEPENDENCIES = $(LIBDIR)/libcurl.la
|
||||
lib512_SOURCES = lib512.c $(SUPPORTFILES)
|
||||
lib512_LDADD = $(LIBDIR)/libcurl.la
|
||||
lib512_DEPENDENCIES = $(LIBDIR)/libcurl.la
|
||||
|
||||
lib513_SOURCES = lib513.c $(SUPPORTFILES)
|
||||
lib513_LDADD = $(LIBDIR)/libcurl.la
|
||||
lib513_DEPENDENCIES = $(LIBDIR)/libcurl.la
|
||||
|
47
tests/libtest/lib513.c
Normal file
47
tests/libtest/lib513.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "test.h"
|
||||
|
||||
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
(void)nmemb;
|
||||
(void)userp;
|
||||
return CURL_READFUNC_ABORT;
|
||||
}
|
||||
|
||||
int test(char *URL)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res=CURLE_OK;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
/* First set the URL that is about to receive our POST. */
|
||||
curl_easy_setopt(curl, CURLOPT_URL, URL);
|
||||
|
||||
/* Now specify we want to POST data */
|
||||
curl_easy_setopt(curl, CURLOPT_POST, TRUE);
|
||||
|
||||
/* Set the expected POST size */
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 1);
|
||||
|
||||
/* we want to use our own read function */
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
|
||||
|
||||
/* pointer to pass to our read function */
|
||||
curl_easy_setopt(curl, CURLOPT_INFILE, NULL);
|
||||
|
||||
/* get verbose debug output please */
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
|
||||
/* include headers in the output */
|
||||
curl_easy_setopt(curl, CURLOPT_HEADER, TRUE);
|
||||
|
||||
/* Perform the request, res will get the return code */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return (int)res;
|
||||
}
|
@@ -748,6 +748,10 @@ sub checkcurl {
|
||||
die "couldn't run '$CURL'"
|
||||
}
|
||||
|
||||
if(!$curl_debug && $torture) {
|
||||
die "can't run torture tests since curl was not build with debug";
|
||||
}
|
||||
|
||||
my $hostname=`hostname`;
|
||||
my $hosttype=`uname -a`;
|
||||
|
||||
@@ -1048,6 +1052,17 @@ sub singletest {
|
||||
my $dumped_core;
|
||||
my $cmdres;
|
||||
|
||||
my @precommand= getpart("client", "precommand");
|
||||
if($precommand[0]) {
|
||||
# this is pure perl to eval!
|
||||
my $code = join("", @precommand);
|
||||
eval $code;
|
||||
if($@) {
|
||||
print "perl: $code\n";
|
||||
print "precommand: $@";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if($gdbthis) {
|
||||
open(GDBCMD, ">log/gdbcmd");
|
||||
@@ -1146,8 +1161,22 @@ sub singletest {
|
||||
}
|
||||
|
||||
if(@protocol) {
|
||||
# verify the sent request
|
||||
my @out = loadarray($SERVERIN);
|
||||
my @out;
|
||||
my $retry = 5;
|
||||
|
||||
# Verify the sent request. Sometimes, like in test 513 on some hosts,
|
||||
# curl will return back faster than the server writes down the request
|
||||
# to its file, so we might need to wait here for a while to see if the
|
||||
# file gets written a bit later.
|
||||
|
||||
while($retry--) {
|
||||
@out = loadarray($SERVERIN);
|
||||
|
||||
if(!$out[0]) {
|
||||
# nothing there yet, wait a while and try again
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
# what to cut off from the live protocol sent by curl
|
||||
my @strip = getpart("verify", "strip");
|
||||
|
@@ -191,10 +191,10 @@ static void logmsg(const char *msg, ...)
|
||||
logfp = fopen(DEFAULT_LOGFILE, "a");
|
||||
|
||||
fprintf(logfp?logfp:stderr, /* write to stderr if the logfile doesn't open */
|
||||
"%02d:%02d:%02d (%d) %s\n",
|
||||
"%02d:%02d:%02d %s\n",
|
||||
curr_time->tm_hour,
|
||||
curr_time->tm_min,
|
||||
curr_time->tm_sec, (int)getpid(), buffer);
|
||||
curr_time->tm_sec, buffer);
|
||||
if(logfp)
|
||||
fclose(logfp);
|
||||
}
|
||||
@@ -447,10 +447,12 @@ void storerequest(char *reqbuf)
|
||||
|
||||
dump = fopen(REQUEST_DUMP, "ab"); /* b is for windows-preparing */
|
||||
if(dump) {
|
||||
fwrite(reqbuf, 1, strlen(reqbuf), dump);
|
||||
size_t len = strlen(reqbuf);
|
||||
fwrite(reqbuf, 1, len, dump);
|
||||
|
||||
fclose(dump);
|
||||
logmsg("Wrote request input to " REQUEST_DUMP);
|
||||
logmsg("Wrote request (%d bytes) input to " REQUEST_DUMP,
|
||||
(int)len);
|
||||
}
|
||||
else {
|
||||
logmsg("Failed to write request input to " REQUEST_DUMP);
|
||||
@@ -482,6 +484,10 @@ static int get_request(int sock, struct httprequest *req)
|
||||
return DOCNUMBER_INTERNAL;
|
||||
}
|
||||
logmsg("Connection closed by client");
|
||||
reqbuf[req->offset]=0;
|
||||
|
||||
/* dump the request receivied so far to the external file */
|
||||
storerequest(reqbuf);
|
||||
return DOCNUMBER_INTERNAL;
|
||||
}
|
||||
req->offset += got;
|
||||
@@ -631,7 +637,8 @@ static int send_doc(int sock, struct httprequest *req)
|
||||
|
||||
fclose(dump);
|
||||
|
||||
logmsg("Response sent (%d bytes)!", responsesize);
|
||||
logmsg("Response sent (%d bytes) and written to " RESPONSE_DUMP,
|
||||
responsesize);
|
||||
|
||||
if(ptr)
|
||||
free(ptr);
|
||||
@@ -769,7 +776,7 @@ int main(int argc, char *argv[])
|
||||
if (msgsock == -1)
|
||||
continue;
|
||||
|
||||
logmsg("** New client connected");
|
||||
logmsg("====> Client connect");
|
||||
|
||||
do {
|
||||
if(get_request(msgsock, &req))
|
||||
@@ -801,7 +808,7 @@ int main(int argc, char *argv[])
|
||||
/* if we got a CONNECT, loop and get another request as well! */
|
||||
} while(req.open || (req.testno == DOCNUMBER_CONNECT));
|
||||
|
||||
logmsg("** Closing client connection");
|
||||
logmsg("====> Client disconnect");
|
||||
sclose(msgsock);
|
||||
|
||||
if (req.testno == DOCNUMBER_QUIT)
|
||||
|
@@ -35,12 +35,15 @@
|
||||
|
||||
# USAGE:
|
||||
# testcurl.pl [curl-daily-name] > output
|
||||
# or:
|
||||
# testcurl.pl --target=your_os > output
|
||||
|
||||
# Updated:
|
||||
# v1.2 8-Mar-04 - rewritten in perl
|
||||
# v1.1 6-Nov-03 - to take an optional parameter, the name of a daily-build
|
||||
# directory. If present, build from that directory, otherwise
|
||||
# perform a normal CVS build.
|
||||
# v1.7 22-Jun-04 - added --target option for other platform targets.
|
||||
# v1.2 8-Mar-04 - rewritten in perl
|
||||
# v1.1 6-Nov-03 - to take an optional parameter, the name of a daily-build
|
||||
# directory. If present, build from that directory, otherwise
|
||||
# perform a normal CVS build.
|
||||
|
||||
use strict;
|
||||
|
||||
@@ -49,20 +52,44 @@ use Cwd;
|
||||
# Turn on warnings (equivalent to -w, which can't be used with /usr/bin/env)
|
||||
BEGIN { $^W = 1; }
|
||||
|
||||
use vars qw($version $fixed $infixed $CURLDIR $CVS $pwd $build $buildlog $buildlogname $gnulikebuild);
|
||||
use vars qw($version $fixed $infixed $CURLDIR $CVS $pwd $build $buildlog
|
||||
$buildlogname $gnulikebuild $targetos $confsuffix $binext);
|
||||
use vars qw($name $email $desc $confopts);
|
||||
|
||||
# version of this script
|
||||
$version='$Revision$';
|
||||
$fixed=0;
|
||||
|
||||
# Determine if we're running from CVS or a canned copy of curl
|
||||
# Determine if we're running from CVS or a canned copy of curl,
|
||||
# or if we got a specific target option
|
||||
$CURLDIR="curl";
|
||||
$CVS=1;
|
||||
if (@ARGV && $ARGV[0]) {
|
||||
$CURLDIR=$ARGV[0];
|
||||
$CVS=0;
|
||||
} else {
|
||||
$CURLDIR="curl";
|
||||
$CVS=1;
|
||||
if ($ARGV[0] =~ /--target=/) {
|
||||
$targetos = (split(/=/, $ARGV[0]))[1];
|
||||
} else {
|
||||
$CURLDIR=$ARGV[0];
|
||||
$CVS=0;
|
||||
}
|
||||
}
|
||||
|
||||
# Do the platform-specific stuff here
|
||||
$gnulikebuild = 1;
|
||||
$confsuffix = '';
|
||||
$binext = '';
|
||||
if ($^O eq 'MSWin32' || defined($targetos)) {
|
||||
$gnulikebuild = 0;
|
||||
if (!defined($targetos)) {
|
||||
# If no target defined on Win32 lets assume vc
|
||||
$targetos = 'vc';
|
||||
}
|
||||
if ($targetos =~ /vc/ || $targetos =~ /mingw32/) {
|
||||
$confsuffix = '-win32';
|
||||
$binext = '.exe';
|
||||
} elsif ($targetos =~ /netware/) {
|
||||
$confsuffix = '-netware';
|
||||
$binext = '.nlm';
|
||||
}
|
||||
}
|
||||
|
||||
$ENV{LANG}="C";
|
||||
@@ -118,11 +145,6 @@ sub mydie($){
|
||||
exit 1;
|
||||
}
|
||||
|
||||
$gnulikebuild = 1;
|
||||
if ($^O eq 'MSWin32') {
|
||||
$gnulikebuild = 0;
|
||||
}
|
||||
|
||||
if (open(F, "setup")) {
|
||||
while (<F>) {
|
||||
if (/(\w+)=(.*)/) {
|
||||
@@ -183,6 +205,7 @@ logit "DESC = $desc";
|
||||
logit "CONFOPTS = $confopts";
|
||||
logit "CFLAGS = ".($ENV{CFLAGS} ? $ENV{CFLAGS} : "");
|
||||
logit "CC = ".($ENV{CC} ? $ENV{CC} : "");
|
||||
logit "target = ".($targetos ? $targetos : "");
|
||||
logit "version = $version";
|
||||
logit "date = ".(scalar gmtime)." UTC";
|
||||
|
||||
@@ -286,7 +309,8 @@ if ($CVS) {
|
||||
mydie "buildconf was NOT successful";
|
||||
}
|
||||
} else {
|
||||
system("buildconf.bat");
|
||||
system("buildconf.bat") if ($^O eq 'MSWin32');
|
||||
# logit "buildconf was successful (dummy message)" if ($^O eq 'linux');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -314,24 +338,28 @@ if ($gnulikebuild) {
|
||||
mydie "configure didn't work";
|
||||
}
|
||||
} else {
|
||||
system("xcopy /s /q ..\\$CURLDIR .");
|
||||
system("xcopy /s /q ..\\$CURLDIR .") if ($^O eq 'MSWin32');
|
||||
if ($^O eq 'linux') {
|
||||
system("cp -ar ../$CURLDIR/* .");
|
||||
system("cp -a ../$CURLDIR/Makefile.dist Makefile");
|
||||
}
|
||||
}
|
||||
|
||||
logit "display lib/config.h";
|
||||
open(F, $gnulikebuild ? "lib/config.h" : "lib/config-win32.h") or die;
|
||||
logit "display lib/config$confsuffix.h";
|
||||
open(F, "lib/config$confsuffix.h") or die;
|
||||
while (<F>) {
|
||||
print if /^ *#/;
|
||||
}
|
||||
close(F);
|
||||
|
||||
logit "display src/config.h";
|
||||
open(F, $gnulikebuild ? "src/config.h" : "src/config-win32.h") or die;
|
||||
logit "display src/config$confsuffix.h";
|
||||
open(F, "src/config$confsuffix.h") or die;
|
||||
while (<F>) {
|
||||
print if /^ *#/;
|
||||
}
|
||||
close(F);
|
||||
|
||||
if (grepfile("define USE_ARES", $gnulikebuild ? "lib/config.h" : "lib/config-win32.h")) {
|
||||
if (grepfile("define USE_ARES", "lib/config$confsuffix.h")) {
|
||||
logit "setup to build ares";
|
||||
|
||||
logit "build ares";
|
||||
@@ -362,7 +390,15 @@ if ($gnulikebuild) {
|
||||
}
|
||||
close(F);
|
||||
} else {
|
||||
open(F, "nmake -i vc|") or die;
|
||||
if ($^O eq 'MSWin32') {
|
||||
if ($targetos =~ /vc/) {
|
||||
open(F, "nmake -i $targetos|") or die;
|
||||
} else {
|
||||
open(F, "make -i $targetos |") or die;
|
||||
}
|
||||
} else {
|
||||
open(F, "make -i $targetos 2>&1 |") or die;
|
||||
}
|
||||
while (<F>) {
|
||||
s/$pwd//g;
|
||||
print;
|
||||
@@ -370,16 +406,19 @@ if ($gnulikebuild) {
|
||||
close(F);
|
||||
}
|
||||
|
||||
my $exe = $gnulikebuild ? "curl" : "curl.exe";
|
||||
if (-f "src/$exe") {
|
||||
logit "src/curl was created fine ($exe)";
|
||||
if (-f "src/curl$binext") {
|
||||
logit "src/curl was created fine (curl$binext)";
|
||||
} else {
|
||||
mydie "src/curl was not created ($exe)";
|
||||
mydie "src/curl was not created (curl$binext)";
|
||||
}
|
||||
|
||||
logit "display $exe --version output";
|
||||
if (defined($targetos) && $targetos =~ /netware/) {
|
||||
#system('../../curlver.sh');
|
||||
} else {
|
||||
logit "display curl$binext --version output";
|
||||
|
||||
system("./src/$exe --version");
|
||||
system("./src/curl$binext --version");
|
||||
}
|
||||
|
||||
if ($gnulikebuild) {
|
||||
logit "run make test-full";
|
||||
|
Reference in New Issue
Block a user