Compare commits

..

96 Commits

Author SHA1 Message Date
Daniel Stenberg
cf8704ccdf 7.7 alpha 2 commit 2001-03-04 16:34:20 +00:00
Daniel Stenberg
5543c2f11f Added include of easy.h to enable libcurl-using programs to *only* have to
include <curl/curl.h>
2001-03-04 15:32:44 +00:00
Daniel Stenberg
90ac37a683 Curl_http() could crash on connection re-use 2001-03-04 15:25:54 +00:00
Daniel Stenberg
dd893fd8a4 ipv6 fix for the 'port' no longer in urldata 2001-03-03 17:50:01 +00:00
Daniel Stenberg
834f079918 fixed for persistant stuff 2001-03-03 16:28:59 +00:00
Daniel Stenberg
2665c763df latest 2001-03-02 15:38:06 +00:00
Daniel Stenberg
d1cfbd51b5 remade the port number stuff so that following locations work and doing
intermixed HTTP and FTP persistant connections also work!
2001-03-02 15:34:15 +00:00
Daniel Stenberg
a3ba6b7a6a Added the disconnect proto 2001-03-02 07:44:22 +00:00
Daniel Stenberg
415d2e7cb7 removed the slist -functions from here
added the Curl_ftp_disconnect function for FTP-specific disconnects
2001-03-02 07:44:05 +00:00
Daniel Stenberg
af4451ec26 improved connections 2001-03-02 07:43:20 +00:00
Daniel Stenberg
7c6562683a extending connectdata 2001-03-02 07:42:35 +00:00
Daniel Stenberg
b6fa2f882c moved the slist-functions here from FTP since they're more generic than simply
for FTP-stuff
2001-03-02 07:42:11 +00:00
Daniel Stenberg
b6c5da337a strdup() takes a const char * now 2001-03-02 07:41:40 +00:00
Daniel Stenberg
9bc24e4876 cleanup better when connects fail 2001-02-28 14:03:46 +00:00
Daniel Stenberg
4af55809e4 added some infof() calls for persistant info 2001-02-22 23:51:17 +00:00
Daniel Stenberg
9c63fcf210 we only allocate the HTTP struct if we need to 2001-02-22 23:41:15 +00:00
Daniel Stenberg
1f17fb5f89 Now persistant connection download works thanks to the Content-Length taken
into account
2001-02-22 23:32:41 +00:00
Daniel Stenberg
584dbffe60 moved the dynamicly set pointers to the connectdata struct 2001-02-22 23:32:02 +00:00
Daniel Stenberg
1c6f6f6972 Douglas R. Horner's corrections applied 2001-02-22 22:33:49 +00:00
Daniel Stenberg
da06a6e7e3 IPv6-adjustments 2001-02-21 17:15:09 +00:00
Daniel Stenberg
46e0937263 corrected memory leaks when re-using connections 2001-02-20 17:46:35 +00:00
Daniel Stenberg
a1d6ad2610 multiple connection support initial commit 2001-02-20 17:35:51 +00:00
Daniel Stenberg
5f3d63ed5b bugfix 2001-02-20 13:58:56 +00:00
Daniel Stenberg
63b5748eb6 -g runs the specified test(s) with gdb! 2001-02-20 13:58:39 +00:00
Daniel Stenberg
e2590430c5 removed the #ifdef 2001-02-20 13:57:50 +00:00
Daniel Stenberg
ada9bc2b24 win32sockets.c is now added with winsock init/cleanup example functions 2001-02-20 13:56:38 +00:00
Daniel Stenberg
43da41e73e Added three tiny PHP examples 2001-02-19 13:39:21 +00:00
Daniel Stenberg
720fa45b56 blurb about different languages and environments added 2001-02-19 13:38:29 +00:00
Daniel Stenberg
7de874c438 just a few PHP/curl examples 2001-02-19 13:38:05 +00:00
Daniel Stenberg
2078c1a01a added two VC++ files for project stuff 2001-02-19 09:29:40 +00:00
Daniel Stenberg
f7a8909372 Made CURLOPT_POST no longer necessary when CURLOPT_POSTFIELDS is used 2001-02-19 09:29:19 +00:00
Daniel Stenberg
250df30e64 Moved a bunch of prototypes from curl.h here, they're no longer public and
I merely stuffed them here before I decide where they belong and if they
are to remain at all
2001-02-19 09:28:10 +00:00
Daniel Stenberg
b887cf7521 removed a bunch of "low level" functions that were never used and are about
to never become reality either
2001-02-19 09:27:12 +00:00
Daniel Stenberg
630e932091 MS VC++ stuff 2001-02-19 09:26:29 +00:00
Daniel Stenberg
cdabd67aa9 Bob Schader updated this 2001-02-19 09:26:01 +00:00
Daniel Stenberg
42e4f9d776 added stuff to the mailing list chapter 2001-02-19 09:25:18 +00:00
Daniel Stenberg
c111033595 removed --continue task (done)
added URL to the NTLM task
2001-02-16 13:41:34 +00:00
Daniel Stenberg
26d1aaccdf 2.2 - rephrased 2001-02-16 13:41:09 +00:00
Daniel Stenberg
ce95d2020f better english timeouted => timed out, as suggested by Larry Fahnoe 2001-02-13 21:57:04 +00:00
Daniel Stenberg
948c3b3aa9 7.6.1 commit 2001-02-13 13:37:14 +00:00
Daniel Stenberg
a140e5311d moved the protocol-specific free to allow easier multiple transfers 2001-02-13 13:34:16 +00:00
Daniel Stenberg
7686ac3f2c ftp response fix, netrc fix for non-http/ftp, https put research 2001-02-12 13:20:04 +00:00
Daniel Stenberg
54778134e4 corrected the prototype 2001-02-12 13:19:09 +00:00
Daniel Stenberg
c59baa06f0 Added 3.10 and a few minor updates 2001-02-12 10:05:09 +00:00
Daniel Stenberg
c107303ade very minor indentation fix 2001-02-12 08:22:19 +00:00
Daniel Stenberg
21b05afc99 removed getenv.h from the package as it was unused 2001-02-12 08:21:45 +00:00
Daniel Stenberg
eebcf7d4f5 Not used anymore 2001-02-09 07:33:58 +00:00
Daniel Stenberg
8d169dfadd Added a failf() call in the error-check just added 2001-02-09 07:14:28 +00:00
Daniel Stenberg
b12e334d83 if netrc is parsed and our host was found in there, set data->bits.user_passwd
unconditioanlly!
2001-02-08 13:53:13 +00:00
Daniel Stenberg
7e36c4437e today's FTP response check fix 2001-02-08 13:52:38 +00:00
Daniel Stenberg
3c7a80a275 postit.c was added as a HTML form file upload example 2001-02-08 08:26:54 +00:00
Daniel Stenberg
61e2a8108b 7.6.1-pre3 2001-02-07 09:49:06 +00:00
Daniel Stenberg
abb14de7e0 GetLine() didn't properly act on -1 lengths returned from Curl_read() 2001-02-07 09:31:03 +00:00
Daniel Stenberg
ccd57e58f6 Added #define ssize_t int since ssize_t doesn't seem to exist in normal
win32 systems
2001-02-07 09:23:54 +00:00
Daniel Stenberg
58d70db92e no longer #includes "getenv.h" 2001-02-07 08:36:23 +00:00
Daniel Stenberg
09f6fc22ed silly me, corrected the strlcat() to compile 2001-02-06 09:12:39 +00:00
Daniel Stenberg
833ce37cb9 new openbsd inspired implementation of strlcat() 2001-02-06 09:08:24 +00:00
Daniel Stenberg
07e7018564 nntp@iname.com's suggested fix to set the libpath 2001-02-06 07:14:44 +00:00
Daniel Stenberg
db70cd28b3 adjusted the IPv6 stuff to compile and build on Linux as well 2001-02-05 23:35:44 +00:00
Daniel Stenberg
f6e2bfd464 Jun-ichiro itojun Hagino's IPv6 adjustments 2001-02-05 23:04:44 +00:00
Daniel Stenberg
1ae5dab8fb Robert Weaver's VC experiences 2001-02-05 22:35:55 +00:00
Daniel Stenberg
c6355e6a43 Added a telnet section 2001-02-05 22:35:21 +00:00
Daniel Stenberg
7d26eb61fe Added a few more configure option explanations 2001-02-05 10:24:12 +00:00
Daniel Stenberg
8613ce377f the new getinfo() stuff and the cygwin patch 2001-02-04 20:10:52 +00:00
Daniel Stenberg
d6b94488a1 Added blurb about the win32 thing that precents a DLL from using a pointer
passed to it from user-space!
2001-02-04 20:10:02 +00:00
Daniel Stenberg
5d7b32d09f extended 5.5 2001-02-04 20:08:42 +00:00
Daniel Stenberg
ed16d30ea8 CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD documented 2001-02-04 20:07:53 +00:00
Daniel Stenberg
6f7c70fbbc CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD were
added as suggested by Bob Schader
2001-02-04 20:03:30 +00:00
Daniel Stenberg
9ab5d30e3b Ingo Ralf Blum made it compile with the newest cygwin 2001-02-04 19:00:27 +00:00
Daniel Stenberg
3b44a3df76 7.6.1-pre2 2001-02-01 07:59:46 +00:00
Daniel Stenberg
572c29a4a3 Added support for --enable-debug 2001-02-01 07:58:49 +00:00
Daniel Stenberg
9464c5430d Curl_read() uses ssize_t now 2001-01-31 15:06:56 +00:00
Daniel Stenberg
a14aaaf23f fixed up the telnet to work (using support from Linus Nielsen) 2001-01-31 15:05:44 +00:00
Daniel Stenberg
c41c5a0ef2 curl_read() and Curl_read() now have ssize_t in the last argument 2001-01-31 13:54:12 +00:00
Daniel Stenberg
c0c0283356 Added a check for a working getaddrinfo() that is required for the IPv6
to be considered enabled
2001-01-31 13:53:31 +00:00
Daniel Stenberg
1bcd3e601a changed order of the range and follow-location checks so that a range-request
will work even when following a Location:
2001-01-30 11:52:59 +00:00
Daniel Stenberg
e721f85c83 new test case 2001-01-29 16:04:19 +00:00
Daniel Stenberg
7015c61b86 removed upload.NN files after each test 2001-01-29 15:07:28 +00:00
Daniel Stenberg
30ec0af109 test case 33, HTTP PUT resume 2001-01-29 14:36:49 +00:00
Daniel Stenberg
f585b66af7 7.6-pre1 2001-01-29 11:36:08 +00:00
Daniel Stenberg
1b77c18430 Added an extra text about % in POST data after comments from Daniel Marell 2001-01-29 10:24:51 +00:00
Daniel Stenberg
bd0bd35771 s/to I/do I/ 2001-01-29 10:16:47 +00:00
Daniel Stenberg
368e3526ea Added "3.9 How to I use curl in PHP?" 2001-01-29 10:16:21 +00:00
Daniel Stenberg
1bbe407a4d The PUT stuff is never set! It is set with the UPLOAD... 2001-01-29 07:26:50 +00:00
Daniel Stenberg
513bc44421 HTTP PUT resume now sends Content-Range: headers as I believe the RFC2616
describes, Bob Schader's research seems to agree.
2001-01-29 07:24:20 +00:00
Daniel Stenberg
4cc76d1576 upload sets HTTP request to PUT for "HTTP upload" 2001-01-29 07:23:11 +00:00
Daniel Stenberg
6dc5c6ffc7 the keep-alive issue 2001-01-27 20:51:31 +00:00
Daniel Stenberg
c69c79dd04 bettersupport for HTTP return codes 300-399 2001-01-27 20:31:51 +00:00
Daniel Stenberg
7fca24b14b PUT resume things
progress meter modified for resume
POST/GET/Location adjustments
2001-01-27 20:25:52 +00:00
Daniel Stenberg
2fa0d3dd5f test case 31 and 32 were added 2001-01-27 20:02:11 +00:00
Daniel Stenberg
3a8210c975 Resume is now done with a Content-Range header instead of a Range header if
the request isn't GET. Presumably, this is how it should be made.
2001-01-27 18:57:07 +00:00
Daniel Stenberg
d69302202d minor output fix 2001-01-27 18:51:10 +00:00
Daniel Stenberg
227662d2ed Added -d that enables easier protocol/server debug overview (it invokes
the servers with their -v options)
2001-01-27 18:50:54 +00:00
Daniel Stenberg
3cb3d43913 added test 29 and 30, HTTP resume and partial download tests 2001-01-27 18:49:48 +00:00
Daniel Stenberg
c8a546c941 The progess meter title get an extra output when a resumed transfer is
taking place
2001-01-27 18:23:59 +00:00
Daniel Stenberg
62fec1d28d data->httpreq was not set properly 2001-01-27 17:58:15 +00:00
91 changed files with 3846 additions and 1654 deletions

184
CHANGES
View File

@@ -6,6 +6,190 @@
History of Changes
** curl 7.7 DOES NOT currently WORK. **
Daniel (4 March 2001)
- Now, there's even a basic check that a re-used connection is still alive
before it is assumed so. A few first tests have proven that libcurl will
then re-connect instead of re-use the dead connection!
Daniel (2 March 2001)
- Now they work intermixed as well. Major coolness!
- More fiddling around, my 'tiny' client I have for testing purposes now has
proved to download both FTP and HTTP with persistant connections. They do
not work intermixed yet though.
Daniel (1 March 2001)
- Wilfredo Sanchez pointed out a minor spelling mistake in a man page and that
curl_slist_append() should take a const char * as second argument. It does
now.
Daniel (22 February 2001)
- The persistant connections start to look good for HTTP. On a subsequent
request, it seems that libcurl now can pick an already existing connection
if a suitable one exists, or it opens a new one.
- Douglas R. Horner mailed me corrections to the curl_formparse() man page
that I applied.
Daniel (20 February 2001)
- Added the docs/examples/win32sockets.c file for our windows friends.
- Linus Nielsen Feltzing provided brand new TELNET functionality and
improvements:
* Negotiation is now passive. Curl does not negotiate until the peer does.
* Possibility to set negotiation options on the command line, currently only
XDISPLOC, TTYPE and NEW_ENVIRON (called NEW_ENV).
* Now sends the USER environment variable if the -u switch is used.
* Use -t to set telnet options (Linus even updated the man page, awesome!)
- Haven't done this big changes to curl for a while. Moved around a lot of
struct fields and stuff to make multiple connections get connection specific
data in separate structs so that they can co-exist in a nice way. See the
mailing lists for discussions around how this is gonna be implemented. Docs
and more will follow.
Studied the HTTP RFC to find out better how persistant connections should
work. Seems cool enough.
Daniel (19 February 2001)
- Bob Schader brought me two files that help set up a MS VC++ libcurl project
easier. He also provided me with an up-to-date libcurl.def file.
- I moved a bunch of prototypes from the public <curl/curl.h> file to the
library private urldata.h. This is because of the upcoming changes. The
low level interface is no longer being planned to become reality.
Daniel (15 February 2001)
- CURLOPT_POST is not required anymore. Just setting the POST string with
CURLOPT_POSTFIELDS will switch on the HTTP POST. Most other things in
libcurl already works this way, i.e they require only the parameter to
switch on a feature so I think this works well with the rest. Setting a NULL
string switches off the POST again.
- Excellent suggestions from Rich Gray, Rick Jones, Johan Nilsson and Bjorn
Reese helped me define a way how to incorporate persistant connections into
libcurl in a very smooth way. If done right, no change may have to be made
to older programs and they will just start using persistant connections when
applicable!
Daniel (13 February 2001)
- Changed the word 'timeouted' to 'timed out' in two different error messages.
Suggested by Larry Fahnoe.
Version 7.6.1
Daniel (9 February 2001)
- Frank Reid and Cain Hopwood provided information and research around a HTTPS
PUT/upload problem we seem to have. No solution found yet.
Daniel (8 February 2001)
- An interesting discussion is how to specify an empty password without having
curl ask for it interactively? The current implmentation takes an empty
password as a request for a password prompt. However, I still want to
support a blank user field. Thus, today if you enter "-u :" (without user
and password) curl will prompt for the password. Tricky. How would you
specify you want the prompt otherwise?
- Made the netrc parse result possible to use for other protocols than FTP and
HTTP (such as the upcoming TELNET fixes).
- The previously mentioned "MSVC++ problems" turned out to be a non-issue.
- Added a HTTP file upload code example in the docs/examples/ section on
request.
- Adjusted the FTP response fix slightly.
Version 7.6.1-pre3
Daniel (7 February 2001)
- SM found a flaw in the response reading function for FTP that could make
libcurl not get out of the loop properly when it should, if libcurl got -1
returned when reading the socket.
- I found a similar mistake in http.c when using a proxy and reading the
results from the proxy connection.
Daniel (6 February 2001)
- A friendly person named "SM" (nntp at iname.com) pointed out that the VC
makefile in src/ needed the libpath set for the debug build to work.
- Daniel Gehriger stepped in to assist with the VC++ stuff Robert Weaver
brought up yesterday.
Daniel (5 February 2001)
- Jun-ichiro itojun Hagino brought a big patch that brings IPv6-awareness to
a bunch of different areas within libcurl.
- Robert Weaver told me about the problems the MS VC++ 6.0 compiler has with
the 'static' keyword on a number of libcurl functions. I might need to add a
patch that redefines static when libcurl is compiled with that compiler.
How do I know when VC++ compiles, anyone?
Daniel (4 February 2001)
- curl_getinfo() was extended with two new options:
CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD. They
return the full assumed content length of the transfer in the given
direction. The CURLINFO_CONTENT_LENGTH_DOWNLOAD will be the Content-Length:
size of a HTTP download. Added descriptions to the man page as well. This
was done after discussions with Bob Schader.
Daniel (3 February 2001)
- Ingo Ralf Blum provided another fix that makes curl build under the more
recent cygwin installations. It seems they've changed the preset defines to
not include WIN32 anymore.
Version 7.6.1-pre2
Daniel (31 January 2001)
- Curl_read() and curl_read() now return a ssize_t for the size, as it had to
be able to return -1. The telnet support crashed due to this and there was a
possibility to weird behaviour all over. Linus Nielsen Feltzing helped me
find this.
- Added a configure.in check for a working getaddrinfo() if IPv6 is requested.
I also made the configure script feature --enable-debug which sets a couple
of compiler options when used. It assumes gcc.
Daniel (30 January 2001)
- I finally took a stab at the long-term FIXME item I've had on myself, and
now libcurl will properly work when doing a HTTP range-request that follows
a Location:. Previously that would make libcurl fail saying that the server
doesn't seem to support range requests.
Daniel (29 January 2001)
- I added a test case for the HTTP PUT resume thing (test case 33).
Version 7.6.1-pre1
Daniel (29 January 2001)
- Yet another Content-Range change. Ok now? Bob Schader checks from his end
and it works for him.
Daniel (27 January 2001)
- So the HTTP PUT resume fix wasn't good. There should appearantly be a
Content-Range header when resuming a PUT.
- I noticed I broke the download-check that verifies that a resumed HTTP
download is actually resumed. It got broke because my new 'httpreq' field
in the main curl struct. I should get slapped. I added a test case for
this now, so I won't be able to ruin this again without noticing.
- Added a test case for content-length verifying when downloading HTTP.
- Made the progress meter title say if the transfer is being transfered. It
makes the output slightly better for resumes.
- When dealing with Location: and HTTP return codes, libcurl will not attempt
to follow the spirit of RFC2616 better. It means that when POSTing to a
URL that is being following to a second place, the standard will judge on
what to do. All HTTP codes except 303 and 305 will cause curl to make a
second POST operation. 303 will make a GET and 305 is not yet supported.
I also wrote two test cases for this POST/GET/Location stuff.
Version 7.6

View File

@@ -39,3 +39,7 @@
/* Define if you want to enable IPv6 support */
#undef ENABLE_IPV6
/* Define this to 'int' if ssize_t is not an available typedefed type */
#undef ssize_t

View File

@@ -23,6 +23,9 @@
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* Define this to 'int' if ssize_t is not an available typedefed type */
#define ssize_t int
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1

View File

@@ -26,6 +26,66 @@ dnl The install stuff has already been taken care of by the automake stuff
dnl AC_PROG_INSTALL
AC_PROG_MAKE_SET
dnl ************************************************************
dnl lame option to switch on debug options
dnl
AC_MSG_CHECKING([whether to enable debug options])
AC_ARG_ENABLE(debug,
[ --enable-debug Enable pedantic debug options
--disable-debug Disable debug options],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
;;
*) AC_MSG_RESULT(yes)
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
CFLAGS="-Wall -pedantic -g"
;;
esac ],
AC_MSG_RESULT(no)
)
dnl
dnl check for working getaddrinfo()
dnl
AC_DEFUN(CURL_CHECK_WORKING_GETADDRINFO,[
AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[
AC_TRY_RUN( [
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
void main(void) {
struct addrinfo hints, *ai;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
if (error) {
exit(1);
}
else {
exit(0);
}
}
],[
ac_cv_working_getaddrinfo="yes"
],[
ac_cv_working_getaddrinfo="no"
],[
ac_cv_working_getaddrinfo="yes"
])])
if test "$ac_cv_working_getaddrinfo" = "yes"; then
AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works])
AC_DEFINE(ENABLE_IPV6, 1, [Define if you want to enable IPv6 support])
fi
])
AC_DEFUN(CURL_CHECK_LOCALTIME_R,
[
dnl check for a few thread-safe functions
@@ -251,7 +311,6 @@ AC_ARG_ENABLE(ipv6,
ipv6=no
;;
*) AC_MSG_RESULT(yes)
AC_DEFINE(ENABLE_IPV6)
ipv6=yes
;;
esac ],
@@ -268,7 +327,6 @@ main()
}
],
AC_MSG_RESULT(yes)
AC_DEFINE(ENABLE_IPV6)
ipv6=yes,
AC_MSG_RESULT(no)
ipv6=no,
@@ -276,6 +334,11 @@ main()
ipv6=no
))
if test "$ipv6" = "yes"; then
CURL_CHECK_WORKING_GETADDRINFO
fi
dnl **********************************************************************
dnl Checks for libraries.
dnl **********************************************************************
@@ -365,6 +428,10 @@ AC_MSG_CHECKING([if Kerberos4 support is requested])
if test "$want_krb4" = yes
then
if test "$ipv6" = "yes"; then
echo krb4 is not compatible with IPv6
exit 1
fi
AC_MSG_RESULT(yes)
dnl Check for & handle argument to --with-krb4
@@ -592,6 +659,9 @@ AC_CHECK_SIZEOF(long double, 8)
# check for 'long long'
AC_CHECK_SIZEOF(long long, 4)
# check for ssize_t
AC_CHECK_TYPE(ssize_t, int)
dnl Get system canonical name
AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED(OS, "${host}")
@@ -622,7 +692,8 @@ AC_CHECK_FUNCS( socket \
setvbuf \
sigaction \
signal \
getpass_r
getpass_r \
strlcat
)
dnl removed 'getpass' check on October 26, 2000
@@ -662,5 +733,6 @@ AC_OUTPUT( Makefile \
packages/Linux/Makefile \
packages/Linux/RPM/Makefile \
packages/Linux/RPM/curl.spec \
packages/Linux/RPM/curl-ssl.spec )
packages/Linux/RPM/curl-ssl.spec \
tiny/Makefile )

101
docs/FAQ
View File

@@ -1,4 +1,4 @@
Updated: January 22, 2001 (http://curl.haxx.se/docs/faq.shtml)
Updated: February 16, 2001 (http://curl.haxx.se/docs/faq.shtml)
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
@@ -30,6 +30,8 @@ FAQ
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
3.7 Can I use curl to delete/rename a file through FTP?
3.8 How do I tell curl to follow HTTP redirects?
3.9 How do I use curl in PHP?
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
4. Running Problems
4.1 Problems connecting to SSL servers.
@@ -52,7 +54,8 @@ FAQ
5.2 How can I receive all data into a large memory chunk?
5.3 How do I fetch multiple files with libcurl?
5.4 Does libcurl do Winsock initing on win32 systems?
5.5 Does CURLOPT_FILE work on win32 ?
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
5.6 What about Keep-Alive or persistant connections?
6. License Issues
6.1 I have a GPL program, can I use the libcurl library?
@@ -104,8 +107,8 @@ FAQ
or with PHP.
Curl is not a single-OS program. Curl exists, compiles, builds and runs
under a wide range of operating systems, including all modern Unixes,
Windows, Amiga, BeOS, OS/2, OS X, QNX etc.
under a wide range of operating systems, including all modern Unixes (and a
bunch of older ones too), Windows, Amiga, BeOS, OS/2, OS X, QNX etc.
1.4 When will you make curl do XXXX ?
@@ -180,11 +183,8 @@ FAQ
2.2. Does curl work/build with other SSL libraries?
Curl has been written to use OpenSSL, although I doubt there would be much
problems using a different library. I just don't know any other free one and
that has limited my possibilities to develop against anything else.
If anyone does "port" curl to use a commercial SSL library, I am of course
very interested in getting the patch!
problems using a different library. If anyone does "port" curl to use a
different SSL library, I am of course very interested in getting the patch!
2.3. Where can I find a copy of LIBEAY32.DLL?
@@ -228,7 +228,7 @@ FAQ
You can't simply use -F or -d at your choice. The web server that will
receive your post assumes one of the formats. If the form you're trying to
"fake" sets the type to 'multipart/form-data', than and only then you must
"fake" sets the type to 'multipart/form-data', then and only then you must
use the -F type. In all the most common cases, you should use -d which then
causes a posting with the type 'application/x-www-form-urlencoded'.
@@ -279,6 +279,29 @@ FAQ
curl -L http://redirector.com
3.9 How do I use curl in PHP?
PHP4 has the ability to use libcurl as an internal module if built with that
option enabled. You then get a set of extra functions that can be used
within your PHP programs. You find all details about those functions in the
curl section in the PHP manual, see the online version at:
http://www.php.net/manual/ref.curl.php
PHP also offers the option to run a command line, and then you can of course
invoke the curl tool using a command line. This is the way to use curl if
you're using PHP3 or PHP4 built without curl module support.
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
Curl adheres to the HTTP spec, which basically means you can play with *any*
protocol that is built ontop of HTTP. Protocols such as SOAP, WEBDAV and
XML-RPC are all such ones. You can use -X to set custom requests and -H to
set custom headers (or replace internally generated ones).
Using libcurl or PHP's curl modules is just as fine and you'd just use the
proper library options to do the same.
4. Running Problems
4.1. Problems connecting to SSL servers.
@@ -310,6 +333,9 @@ FAQ
In win32, the standard DOS shell treats the %-letter specially and you may
need to quote the string properly when % is used in it.
Also note that if you want the literal %-letter to be part of the data you
pass in a POST using -d/--data you must encode it as '%25'.
4.3. How can I use {, }, [ or ] to specify multiple URLs?
Because those letters have a special meaning to the shell, and to be used in
@@ -408,7 +434,8 @@ FAQ
4.9. Curl can't authenticate to the server that requires NTLM?
NTLM is a Microsoft proprietary protocol. Unfortunately, curl does not
currently support that.
currently support that. Proprietary formats are evil. You should not use
such ones.
5. libcurl Issues
@@ -473,18 +500,28 @@ FAQ
use several different libraries and parts, and there's no reason for every
single library to do this.
5.5 Does CURLOPT_FILE work on win32 ?
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
Yes, but you cannot open a FILE * and pass the pointer to a DLL and have
that DLL use the FILE *. You must use CURLOPT_WRITEFUNCTION as well to set a
function that writes the file, even if that simply writes the data to the
specified FILE*.
that DLL use the FILE *. If you set CURLOPT_FILE you must also use
CURLOPT_WRITEFUNCTION as well to set a function that writes the file, even
if that simply writes the data to the specified FILE*. Similarly, if you use
CURLOPT_INFILE you must also specify CURLOPT_READFUNCTION.
(provided by Joel DeYoung)
(Provided by Joel DeYoung and Bob Schader)
5.6 What about Keep-Alive or persistant connections?
This is closely related to issue 5.3. Since libcurl has no real support
for doing multiple file transfers, there's no support for Keep-Alive or
persistant connections either.
This is of course subject to change as soon as libcurl gets support for
multiple files. Feel free to join in and make this change happen sooner!
6. License Issues
NOTE: This section is now updated to concern curl 7.5.2 or later!
NOTE: This section concerns curl 7.5.2 or later!
Curl and libcurl are released under a MIT/X derivate license *or* the MPL,
the Mozilla Public License. To get a really good answer to your license
@@ -502,27 +539,25 @@ FAQ
6.2. I have a closed-source program, can I use the libcurl library?
Yes.
Yes!
libcurl does not put any restrictions on the program that uses the
library.
libcurl does not put any restrictions on the program that uses the library.
6.3. I have a BSD licensed program, can I use the libcurl library?
Yes.
Yes!
libcurl does not put any restrictions on the program that uses the
library.
libcurl does not put any restrictions on the program that uses the library.
6.4. I have a program that uses LGPL libraries, can I use libcurl?
Yes.
Yes!
The LGPL license don't clash with other licenses.
The LGPL license doesn't clash with other licenses.
6.5. Can I modify curl/libcurl for my program and keep the changes secret?
Yes.
Yes!
The MIT/X derivate license practically allows you to do almost anything with
the sources, on the condition that the copyright texts in the sources are
@@ -530,9 +565,11 @@ FAQ
6.6. Can you please change the curl/libcurl license to XXXX?
No. We carefully picked this license years ago and a large amount of people
have contributed with source code knowing that this is the license we
use. This license puts the restrictions we want on curl/libcurl and it does
not spread to other programs or libraries that use it. The recent dual
license modification should make it possible for everyone to use libcurl or
curl in their projects, no matter what license they already have in use.
No.
We carefully picked this license years ago and a large amount of people have
contributed with source code knowing that this is the license we use. This
license puts the restrictions we want on curl/libcurl and it does not spread
to other programs or libraries that use it. The recent dual license
modification should make it possible for everyone to use libcurl or curl in
their projects, no matter what license they already have in use.

View File

@@ -20,6 +20,7 @@ Misc
- compiles on win32
- redirectable stderr
- use selected network interface for outgoing traffic
- IPv6 support
HTTP
- GET
@@ -28,7 +29,7 @@ HTTP
- POST
- multipart POST
- authentication
- resume
- resume (both GET and PUT)
- follow redirects
- maximum amount of redirects to follow
- custom HTTP request

View File

@@ -84,9 +84,10 @@ UNIX
KNOWN PROBLEMS
If you happen to have autoconf installed, but a version older than
2.12 you will get into trouble. Then you can still build curl by
issuing these commands: (from Ralph Beckmann)
If you happen to have autoconf installed, but a version older than 2.12
you will get into trouble. Then you can still build curl by issuing these
commands (note that this requires curl to be built staticly): (from Ralph
Beckmann)
./configure [...]
cd lib; make; cd ..
@@ -139,6 +140,14 @@ UNIX
./configure --with-krb4=/usr/athena
If your system support shared libraries, but you want to built a static
version only, you can disable building the shared version by using:
./configure --disable-shared
If you're a curl developer and use gcc, you might want to enable more
debug options with the --enable-debug option.
Win32
=====

View File

@@ -726,16 +726,41 @@ KERBEROS4 FTP TRANSFER
There's no use for a password on the -u switch, but a blank one will make
curl ask for one and you already entered the real password to kauth.
MAILING LIST
TELNET
We have an open mailing list to discuss curl, its development and things
relevant to this.
The curl telnet support is basic and very easy to use. Curl passes all data
passed to it on stdin to the remote server. Connect to a remote telnet
server using a command line similar to:
To subscribe, mail curl-request@contactor.se with "subscribe <fill in your
email address>" in the body.
curl telnet://remote.server.com
To post to the list, mail curl@contactor.se.
And enter the data to pass to the server on stdin. The result will be sent
to stdout or to the file you specify with -o.
To unsubcribe, mail curl-request@contactor.se with "unsubscribe <your
subscribed email address>" in the body.
You might want the -N/--no-buffer option to switch off the buffered output
for slow connections or similar.
NOTE: the telnet protocol does not specify any way to login with a specified
user and password so curl can't do that automatically. To do that, you need
to track when the login prompt is received and send the username and
password accordingly.
MAILING LISTS
For your convenience, we have several open mailing lists to discuss curl,
its development and things relevant to this.
To subscribe to the main curl list, mail curl-request@contactor.se with
"subscribe <fill in your email address>" in the body.
To subscribe to the libcurl users list, follow the instructions at
http://curl.haxx.se/mail/
To subscribe to the curl announce list, to only get information about new
releases, follow the instructions at http://curl.haxx.se/mail/
To subscribe to the curl-and-PHP list in which curl using with PHP is
discussed, follow the instructions at http://curl.haxx.se/mail/
Please direct curl questions, feature requests and trouble reports to one of
these mailing lists instead of mailing any individual.

View File

@@ -23,11 +23,8 @@ For the future
URLs mentioned in the list. I figure -O or something would have to be
implied by such an action.
* Improve the regular progress meter with --continue is used. It should be
noticable when there's a resume going on.
* Add a command line option that allows the output file to get the same time
stamp as the remote file. We already are capable of fetching the remote
stamp as the remote file. libcurl already is capable of fetching the remote
file's date.
* Make the SSL layer option capable of using the Mozilla Security Services as
@@ -58,13 +55,15 @@ For the future
started in October 1999 but halted again since it proved more work than we
thought. It is still a good idea to implement though.
* Authentication: NTLM. It would be cool to support that MS crap called NTLM
* Authentication: NTLM. It would be to support that MS crap called NTLM
authentication. MS proxies and servers sometime require that. Since that
protocol is a proprietary one, it involves reverse engineering and network
sniffing. This should however be a library-based functionality. There are a
few different efforts "out there" to make open source HTTP clients support
this and it should be possible to take advantage of other people's hard
work. http://modntlm.sourceforge.net/ is one.
work. http://modntlm.sourceforge.net/ is one. There's a web page at
http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
engineered info.
* RFC2617 compliance, "Digest Access Authentication"
A valid test page seem to exist at:

View File

@@ -425,11 +425,14 @@ If this option is used twice, the second will again disable mute.
When used with -s it makes curl show error message if it fails.
If this option is used twice, the second will again disable show error.
.IP "-t/--upload"
.B Deprecated. Use '-T -' instead.
Transfer the stdin data to the specified file. Curl will read
everything from stdin until EOF and store with the supplied name. If
this is used on a http(s) server, the PUT command will be used.
.IP "-t/--telnet-option <OPT=val>"
Pass options to the telnet protocol. Supported options are:
TTYPE=<term> Sets the terminal type.
XDISPLOC=<X display> Sets the X display location.
NEW_ENV=<var,val> Sets an environment variable.
.IP "-T/--upload-file <file>"
Like -t, but this transfers the specified local file. If there is no
file part in the specified URL, Curl will append the local file
@@ -758,7 +761,7 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Lars J. Aas <larsa@sim.no>
- J<>rn Hartroth <Joern.Hartroth@computer.org>
- Matthew Clarke <clamat@van.maves.ca>
- Linus Nielsen <Linus.Nielsen@haxx.se>
- Linus Nielsen Feltzing <linus@haxx.se>
- Felix von Leitner <felix@convergence.de>
- Dan Zitter <dzitter@zitter.net>
- Jongki Suwandi <Jongki.Suwandi@eng.sun.com>
@@ -788,6 +791,7 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Loic Dachary <loic@senga.org>
- Robert Weaver <robert.weaver@sabre.com>
- Ingo Ralf Blum <ingoralfblum@ingoralfblum.com>
- Jun-ichiro itojun Hagino <itojun@iijlab.net>
.SH WWW
http://curl.haxx.se

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_easy_init 3 "22 November 2000" "Curl 7.5" "libcurl Manual"
.TH curl_easy_init 3 "4 February 2001" "Curl 7.6.1" "libcurl Manual"
.SH NAME
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
.SH SYNOPSIS
@@ -81,6 +81,14 @@ than one request if FOLLOWLOCATION is true.
Pass a pointer to a long to receive the result of the certification
verification that was requested (using the CURLOPT_SSL_VERIFYPEER option to
curl_easy_setopt). (Added in 7.4.2)
.TP
.B CURLINFO_CONTENT_LENGTH_DOWNLOAD
Pass a pointer to a double to receive the content-length of the download.
(Added in 7.6.1)
.TP
.B CURLINFO_CONTENT_LENGTH_UPLOAD
Pass a pointer to a double to receive the specified size of the upload.
(Added in 7.6.1)
.PP
.SH RETURN VALUE

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_easy_perform 3 "25 Jan 2001" "Curl 7.0" "libcurl Manual"
.TH curl_easy_perform 3 "1 Mar 2001" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_easy_perform - Do the actual transfer in a "easy" session
.SH SYNOPSIS
@@ -25,7 +25,7 @@ again first.
.I <curl/curl.h>
defines. If the CURLOPT_ERRORBUFFER was set with
.I curl_easy_setopt
there willo be a readable error message in the error buffer when non-zero is
there will be a readable error message in the error buffer when non-zero is
returned.
.SH "SEE ALSO"
.BR curl_easy_init "(3), " curl_easy_setopt "(3), "

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_easy_setopt 3 "28 November 2000" "Curl 7.5" "libcurl Manual"
.TH curl_easy_setopt 3 "2 February 2001" "Curl 7.5" "libcurl Manual"
.SH NAME
curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS
@@ -35,6 +35,12 @@ Data pointer to pass instead of FILE * to the file write function. Note that
if you specify the
.I CURLOPT_WRITEFUNCTION
, this is the pointer you'll get as input.
NOTE: If you're using libcurl as a win32 .DLL, you MUST use a
.I CURLOPT_WRITEFUNCTION
if you set the
.I CURLOPT_FILE
option.
.TP
.B CURLOPT_WRITEFUNCTION
Function pointer that should use match the following prototype:
@@ -53,6 +59,12 @@ Data pointer to pass instead of FILE * to the file read function. Note that if
you specify the
.I CURLOPT_READFUNCTION
, this is the pointer you'll get as input.
NOTE: If you're using libcurl as a win32 .DLL, you MUST use a
.I CURLOPT_READFUNCTION
if you set the
.I CURLOPT_INFILE
option.
.TP
.B CURLOPT_READFUNCTION
Function pointer that should use match the following prototype:

View File

@@ -2,13 +2,13 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_formparse 3 "6 June 2000" "Curl 7.0" "libcurl Manual"
.TH curl_formparse 3 "22 February 2001" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_formparse - add a section to a multipart/formdata HTTP POST
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "CURLcode *curl_formparse(char *" string, "struct HttpPost **" firstitem,
.BI "CURLcode curl_formparse(char *" string, "struct HttpPost **" firstitem,
.BI "struct HttpPost ** "lastitem ");"
.ad
.SH DESCRIPTION
@@ -42,14 +42,14 @@ Add a form field named 'name' with the contents as read from the local files
named 'filename1' and 'filename2'. This is identical to the upper, except that
you get the contents of several files in one section.
.TP
.B [name]=@[filename];[content-type]
.B [name]=@[filename];[type=<content-type>]
Whenever you specify a file to read from, you can optionally specify the
content-type as well. The content-type is passed to the server together with
the contents of the file. curl_formparse() will guess content-type for a
number of well-known extensions and otherwise it will set it to binary. You
can override the internal decision by using this option.
.TP
.B [name]=@[filename1,filename2,...];[content-type]
.B [name]=@[filename1,filename2,...];[type=<content-type>]
When you specify several files to read the contents from, you can set the
content-type for all of them in the same way as with a single file.
.PP

View File

@@ -2,14 +2,14 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_slist_append 3 "2 June 2000" "Curl 7.0" "libcurl Manual"
.TH curl_slist_append 3 "1 Mar 2001" "Curl 7.7" "libcurl Manual"
.SH NAME
curl_slist_append - add a string to an slist
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "struct curl_slist *curl_slist_append(struct curl_slit *" list,
.BI "char * "string ");"
.BI "const char * "string ");"
.ad
.SH DESCRIPTION
curl_slist_append() appends a specified string to a linked list of

View File

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

View File

@@ -6,3 +6,6 @@ advantage of libcurl.
If you end up with other small but still useful example sources, please mail
them for submission in future packages and on the web site.
There are examples for different languages and environments. Browse around to
find those that fit you.

View File

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

View File

@@ -0,0 +1,10 @@
#
# The PHP curl module supports the received page to be returned in a variable
# if told.
#
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.myurl.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result=curl_exec ($ch);
curl_close ($ch);

71
docs/examples/postit.c Normal file
View File

@@ -0,0 +1,71 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* Example code that uploads a file name 'foo' to a remote script that accepts
* "HTML form based" (as described in RFC1738) uploads using HTTP POST.
*
* The imaginary form we'll fill in looks like:
*
* <form method="post" enctype="multipart/form-data" action="examplepost.cgi">
* Enter file: <input type="file" name="sendfile" size="40">
* Enter file name: <input type="text" name="filename" size="30">
* <input type="submit" value="send" name="submit">
* </form>
*
* This exact source code has not been verified to work.
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
struct HttpPost *formpost=NULL;
struct HttpPost *lastptr=NULL;
/* Fill in the file upload field */
curl_formparse("sendfile=@foo",
&formpost,
&lastptr);
/* Fill in the filename field */
curl_formparse("filename=foo",
&formpost,
&lastptr);
/* Fill in the submit field too, even if this is rarely needed */
curl_formparse("submit=send",
&formpost,
&lastptr);
curl = curl_easy_init();
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/examplepost.cgi");
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
}
return 0;
}

View File

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

View File

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

View File

@@ -0,0 +1,13 @@
#
# A very simple example that gets a HTTP page.
#
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, "http://www.zend.com/");
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_exec ($ch);
curl_close ($ch);

View File

@@ -0,0 +1,12 @@
#
# A very simple PHP example that sends a HTTP POST to a remote site
#
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.mysite.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "postvar1=value1&postvar2=value2&postvar3=value3");
curl_exec ($ch);
curl_close ($ch);

View File

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

View File

@@ -158,6 +158,9 @@ typedef enum {
CURLE_BAD_PASSWORD_ENTERED, /* when the my_getpass() returns fail */
CURLE_TOO_MANY_REDIRECTS , /* catch endless re-direct loops */
CURLE_UNKNOWN_TELNET_OPTION , /* User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX , /* Malformed telnet option */
CURL_LAST
} CURLcode;
@@ -406,6 +409,9 @@ typedef enum {
document! Pass a NULL to shut it off. */
CINIT(FILETIME, OBJECTPOINT, 69),
/* This points to a linked list of telnet options */
CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
@@ -452,8 +458,8 @@ char *curl_getenv(char *variable);
char *curl_version(void);
/* This is the version number */
#define LIBCURL_VERSION "7.6"
#define LIBCURL_VERSION_NUM 0x070600
#define LIBCURL_VERSION "7.7-alpha2"
#define LIBCURL_VERSION_NUM 0x070000
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
@@ -461,184 +467,8 @@ struct curl_slist {
struct curl_slist *next;
};
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Inits libcurl globally. This must be used before any libcurl calls can
* be used. This may install global plug-ins or whatever. (This does not
* do winsock inits in Windows.)
*
* EXAMPLE
*
* curl_init();
*
*/
CURLcode curl_init(void);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Frees libcurl globally. This must be used after all libcurl calls have
* been used. This may remove global plug-ins or whatever. (This does not
* do winsock cleanups in Windows.)
*
* EXAMPLE
*
* curl_free(curl);
*
*/
void curl_free(void);
/*
* NAME curl_open()
*
* DESCRIPTION
*
* Opens a general curl session. It does not try to connect or do anything
* on the network because of this call. The specified URL is only required
* to enable curl to figure out what protocol to "activate".
*
* A session should be looked upon as a series of requests to a single host. A
* session interacts with one host only, using one single protocol.
*
* The URL is not required. If set to "" or NULL, it can still be set later
* using the curl_setopt() function. If the curl_connect() function is called
* without the URL being known, it will return error.
*
* EXAMPLE
*
* CURLcode result;
* CURL *curl;
* result = curl_open(&curl, "http://curl.haxx.nu/libcurl/");
* if(result != CURL_OK) {
* return result;
* }
* */
CURLcode curl_open(CURL **curl, char *url);
/*
* NAME curl_setopt()
*
* DESCRIPTION
*
* Sets a particular option to the specified value.
*
* EXAMPLE
*
* CURL curl;
* curl_setopt(curl, CURL_HTTP_FOLLOW_LOCATION, TRUE);
*/
CURLcode curl_setopt(CURL *handle, CURLoption option, ...);
/*
* NAME curl_close()
*
* DESCRIPTION
*
* Closes a session previously opened with curl_open()
*
* EXAMPLE
*
* CURL *curl;
* CURLcode result;
*
* result = curl_close(curl);
*/
CURLcode curl_close(CURL *curl); /* the opposite of curl_open() */
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
size_t *n);
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n);
/*
* NAME curl_connect()
*
* DESCRIPTION
*
* Connects to the peer server and performs the initial setup. This function
* writes a connect handle to its second argument that is a unique handle for
* this connect. This allows multiple connects from the same handle returned
* by curl_open().
*
* EXAMPLE
*
* CURLCode result;
* CURL curl;
* CURLconnect connect;
* result = curl_connect(curl, &connect);
*/
CURLcode curl_connect(CURL *curl, CURLconnect **in_connect);
/*
* NAME curl_do()
*
* DESCRIPTION
*
* (Note: May 3rd 2000: this function does not currently allow you to
* specify a document, it will use the one set previously)
*
* This function asks for the particular document, file or resource that
* resides on the server we have connected to. You may specify a full URL,
* just an absolute path or even a relative path. That means, if you're just
* getting one file from the remote site, you can use the same URL as input
* for both curl_open() as well as for this function.
*
* In the even there is a host name, port number, user name or password parts
* in the URL, you can use the 'flags' argument to ignore them completely, or
* at your choice, make the function fail if you're trying to get a URL from
* different host than you connected to with curl_connect().
*
* You can only get one document at a time using the same connection. When one
* document has been received you can although request again.
*
* When the transfer is done, curl_done() MUST be called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_do(connect, url, CURL_DO_NONE); */
CURLcode curl_do(CURLconnect *in_conn);
/*
* NAME curl_done()
*
* DESCRIPTION
*
* When the transfer following a curl_do() call is done, this function should
* get called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_done(connect); */
CURLcode curl_done(CURLconnect *connect);
/*
* NAME curl_disconnect()
*
* DESCRIPTION
*
* Disconnects from the peer server and performs connection cleanup.
*
* EXAMPLE
*
* CURLcode result;
* CURLconnect *connect;
* result = curl_disconnect(connect); */
CURLcode curl_disconnect(CURLconnect *connect);
struct curl_slist *curl_slist_append(struct curl_slist *, const char *);
void curl_slist_free_all(struct curl_slist *);
/*
* NAME curl_getdate()
@@ -676,9 +506,16 @@ typedef enum {
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14,
CURLINFO_LASTONE = 15
CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
CURLINFO_LASTONE = 17
} CURLINFO;
/* unfortunately, the easy.h include file needs the options and info stuff
before it can be included! */
#include <curl/easy.h> /* nothing in curl is fun without the easy stuff */
/*
* NAME curl_getinfo()
*
@@ -693,6 +530,20 @@ typedef enum {
*/
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...);
typedef enum {
CURLCLOSEPOLICY_NONE, /* first, never use this */
CURLCLOSEPOLICY_OLDEST,
CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
CURLCLOSEPOLICY_LEAST_TRAFFIC,
CURLCLOSEPOLICY_SLOWEST,
CURLCLOSEPOLICY_CALLBACK,
CURLCLOSEPOLICY_LAST /* last, never use this */
} curl_closepolicy;
#ifdef __cplusplus
}
#endif

View File

@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = getdate.y \
Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \
libcurl.def dllinit.c
libcurl.def dllinit.c curllib.dsp curllib.dsw
lib_LTLIBRARIES = libcurl.la
@@ -55,7 +55,7 @@ dict.c ftp.h if2ip.c speedcheck.c url.h \
dict.h getdate.c if2ip.h speedcheck.h urldata.h \
getdate.h ldap.c ssluse.c version.c \
getenv.c ldap.h ssluse.h \
escape.c getenv.h mprintf.c telnet.c \
escape.c mprintf.c telnet.c \
escape.h getpass.c netrc.c telnet.h \
getinfo.c transfer.c strequal.c strequal.h easy.c \
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h

367
lib/curllib.dsp Normal file
View File

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

29
lib/curllib.dsw Normal file
View File

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

View File

@@ -141,7 +141,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef);
}
Curl_sendf(data->firstsocket, conn,
Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH "
"%s " /* database */
@@ -154,7 +154,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word
);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
@@ -191,7 +191,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef);
}
Curl_sendf(data->firstsocket, conn,
Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE "
"%s " /* database */
@@ -202,7 +202,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word
);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
@@ -220,13 +220,13 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':')
ppath[i] = ' ';
}
Curl_sendf(data->firstsocket, conn,
Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n"
"QUIT\n",
ppath);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL);
if(result)

560
lib/ftp.c
View File

@@ -88,76 +88,8 @@
/* easy-to-use macro: */
#define ftpsendf Curl_ftpsendf
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
struct curl_slist *item;
/* if caller passed us a NULL, return now */
if (!list)
return NULL;
/* loop through to find the last item */
item = list;
while (item->next) {
item = item->next;
}
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data)
{
struct curl_slist *last;
struct curl_slist *new_item;
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
}
else {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL;
}
if (list) {
last = slist_get_last(list);
last->next = new_item;
return list;
}
/* if this is the first item, then new_item *is* the list */
return new_item;
}
/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
struct curl_slist *next;
struct curl_slist *item;
if (!list)
return;
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
free(item);
item = next;
} while (next);
}
static CURLcode AllowServerConnect(struct UrlData *data,
struct connectdata *conn,
int sock)
{
fd_set rdset;
@@ -199,7 +131,7 @@ static CURLcode AllowServerConnect(struct UrlData *data,
}
infof(data, "Connection accepted from server\n");
data->secondarysocket = s;
conn->secondarysocket = s;
}
break;
}
@@ -221,7 +153,7 @@ int Curl_GetFTPResponse(int sockfd, char *buf,
int *ftpcode)
{
int nread;
size_t keepon=TRUE;
ssize_t keepon=TRUE;
char *ptr;
int timeout = 3600; /* in seconds */
struct timeval interval;
@@ -282,6 +214,10 @@ int Curl_GetFTPResponse(int sockfd, char *buf,
*/
if(CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &keepon))
keepon = FALSE;
else if(keepon <= 0) {
error = SELECT_ERROR;
failf(data, "Connection aborted");
}
else if ((*ptr == '\n') || (*ptr == '\r'))
keepon = FALSE;
}
@@ -358,23 +294,25 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp;
conn->proto.ftp = ftp;
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount;
ftp->user = data->user;
ftp->passwd = data->passwd;
/* duplicate to keep them even when the data struct changes */
ftp->user = strdup(data->user);
ftp->passwd = strdup(data->passwd);
if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket,
data->hostname, data->remote_port);
result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
conn->hostname, conn->remote_port);
if(CURLE_OK != result)
return result;
}
/* The first thing we do is wait for the "220*" line: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -394,7 +332,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
set a valid level */
sec_request_prot(conn, data->krb4_level);
data->cmdchannel = fdopen(data->firstsocket, "w");
data->cmdchannel = fdopen(conn->firstsocket, "w");
if(sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n");
@@ -404,10 +342,10 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
#endif
/* send USER */
ftpsendf(data->firstsocket, conn, "USER %s", ftp->user);
ftpsendf(conn->firstsocket, conn, "USER %s", ftp->user);
/* wait for feedback */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -420,8 +358,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
else if(ftpcode == 331) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
ftpsendf(data->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
ftpsendf(conn->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -465,6 +403,58 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_FTP_WEIRD_USER_REPLY;
}
/* send PWD to discover our entry point */
ftpsendf(conn->firstsocket, conn, "PWD");
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(ftpcode == 257) {
char *dir = (char *)malloc(nread+1);
char *store=dir;
char *ptr=&buf[4]; /* start on the first letter */
/* Reply format is like
257<space>"<directory-name>"<space><commentary> and the RFC959 says
The directory name can contain any character; embedded double-quotes
should be escaped by double-quotes (the "quote-doubling" convention).
*/
if('\"' == *ptr) {
/* it started good */
ptr++;
while(ptr && *ptr) {
if('\"' == *ptr) {
if('\"' == ptr[1]) {
/* "quote-doubling" */
*store = ptr[1];
ptr++;
}
else {
/* end of path */
*store = '\0'; /* zero terminate */
break; /* get out of this loop */
}
}
else
*store = *ptr;
store++;
ptr++;
}
ftp->entrypath =dir; /* remember this */
infof(data, "Entry path is '%s'\n", ftp->entrypath);
}
else {
/* couldn't get the path */
}
}
else {
/* We couldn't read the PWD response! */
}
return CURLE_OK;
}
@@ -473,7 +463,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
CURLcode Curl_ftp_done(struct connectdata *conn)
{
struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp;
struct FTP *ftp = conn->proto.ftp;
size_t nread;
char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */
@@ -488,7 +478,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
}
else {
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
(data->maxdownload != *ftp->bytecountp)) {
(conn->maxdownload != *ftp->bytecountp)) {
failf(data, "Received only partial file");
return CURLE_PARTIAL_FILE;
}
@@ -498,16 +488,16 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
}
}
#ifdef KRB4
sec_fflush_fd(conn, data->secondarysocket);
sec_fflush_fd(conn, conn->secondarysocket);
#endif
/* shut down the socket to inform the server we're done */
sclose(data->secondarysocket);
data->secondarysocket = -1;
sclose(conn->secondarysocket);
conn->secondarysocket = -1;
if(!data->bits.no_body) {
/* now let's see what the server says about the transfer we
just performed: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -525,9 +515,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
while (qitem) {
/* Send string */
if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data);
ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -541,9 +531,6 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
}
}
free(ftp);
data->proto.ftp=NULL; /* it is gone */
return CURLE_OK;
}
@@ -564,10 +551,13 @@ CURLcode _ftp(struct connectdata *conn)
#if defined (HAVE_INET_NTOA_R)
char ntoa_buf[64];
#endif
#ifdef ENABLE_IPV6
struct addrinfo *ai;
#endif
struct curl_slist *qitem; /* QUOTE item */
/* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->proto.ftp;
struct FTP *ftp = conn->proto.ftp;
long *bytecountp = ftp->bytecountp;
int ftpcode; /* for ftp status */
@@ -579,9 +569,9 @@ CURLcode _ftp(struct connectdata *conn)
while (qitem) {
/* Send string */
if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data);
ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -595,10 +585,27 @@ CURLcode _ftp(struct connectdata *conn)
}
}
if(conn->bits.reuse) {
/* This is a re-used connection. Since we change directory to where the
transfer is taking place, we must now get back to the original dir
where we ended up after login: */
ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->entrypath);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(ftpcode != 250) {
failf(data, "Couldn't change back to directory %s", ftp->entrypath);
return CURLE_FTP_ACCESS_DENIED;
}
}
/* change directory first! */
if(ftp->dir && ftp->dir[0]) {
ftpsendf(data->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -611,9 +618,9 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.get_filetime && ftp->file) {
/* we have requested to get the modified-time of the file, this is yet
again a grey area as the MDTM is not kosher RFC959 */
ftpsendf(data->firstsocket, conn, "MDTM %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "MDTM %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -647,10 +654,10 @@ CURLcode _ftp(struct connectdata *conn)
/* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */
ftpsendf(data->firstsocket, conn, "TYPE %s",
ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -661,9 +668,9 @@ CURLcode _ftp(struct connectdata *conn)
CURLE_FTP_COULDNT_SET_BINARY;
}
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -702,6 +709,178 @@ CURLcode _ftp(struct connectdata *conn)
/* We have chosen to use the PORT command */
if(data->bits.ftp_use_port) {
#ifdef ENABLE_IPV6
struct addrinfo hints, *res, *ai;
struct sockaddr_storage ss;
int sslen;
char hbuf[NI_MAXHOST];
char *localaddr;
struct sockaddr *sa=(struct sockaddr *)&ss;
#ifdef NI_WITHSCOPEID
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
#else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif
unsigned char *ap;
unsigned char *pp;
int alen, plen;
char portmsgbuf[4096], tmp[4096];
char *p;
char *mode[] = { "EPRT", "LPRT", "PORT", NULL };
char **modep;
/*
* we should use Curl_if2ip? given pickiness of recent ftpd,
* I believe we should use the same address as the control connection.
*/
sslen = sizeof(ss);
if (getsockname(conn->firstsocket, (struct sockaddr *)&ss, &sslen) < 0)
return CURLE_FTP_PORT_FAILED;
if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0,
niflags))
return CURLE_FTP_PORT_FAILED;
memset(&hints, 0, sizeof(hints));
hints.ai_family = sa->sa_family;
/*hints.ai_family = ss.ss_family;
this way can be used if sockaddr_storage is properly defined, as glibc
2.1.X doesn't do*/
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo(hbuf, "0", &hints, &res))
return CURLE_FTP_PORT_FAILED;
portsock = -1;
for (ai = res; ai; ai = ai->ai_next) {
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (portsock < 0)
continue;
if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
close(portsock);
portsock = -1;
continue;
}
if (listen(portsock, 1) < 0) {
close(portsock);
portsock = -1;
continue;
}
break;
}
if (portsock < 0) {
failf(data, strerror(errno));
freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED;
}
sslen = sizeof(ss);
if (getsockname(portsock, sa, &sslen) < 0) {
failf(data, strerror(errno));
freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED;
}
for (modep = mode; modep && *modep; modep++) {
int lprtaf, eprtaf;
switch (sa->sa_family) {
case AF_INET:
ap = (char *)&((struct sockaddr_in *)&ss)->sin_addr;
alen = sizeof(((struct sockaddr_in *)&ss)->sin_addr);
pp = (char *)&((struct sockaddr_in *)&ss)->sin_port;
plen = sizeof(((struct sockaddr_in *)&ss)->sin_port);
lprtaf = 4;
eprtaf = 1;
break;
case AF_INET6:
ap = (char *)&((struct sockaddr_in6 *)&ss)->sin6_addr;
alen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_addr);
pp = (char *)&((struct sockaddr_in6 *)&ss)->sin6_port;
plen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_port);
lprtaf = 6;
eprtaf = 2;
break;
default:
ap = pp = NULL;
lprtaf = eprtaf = -1;
break;
}
if (strcmp(*modep, "EPRT") == 0) {
if (eprtaf < 0)
continue;
if (getnameinfo((struct sockaddr *)&ss, sslen,
portmsgbuf, sizeof(portmsgbuf), tmp, sizeof(tmp), niflags))
continue;
/* do not transmit IPv6 scope identifier to the wire */
if (sa->sa_family == AF_INET6) {
char *q = strchr(portmsgbuf, '%');
if (q)
*q = '\0';
}
ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
portmsgbuf, tmp);
} else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) {
int i;
if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0)
continue;
if (strcmp(*modep, "PORT") == 0 && sa->sa_family != AF_INET)
continue;
portmsgbuf[0] = '\0';
if (strcmp(*modep, "LPRT") == 0) {
snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
goto again;
}
}
for (i = 0; i < alen; i++) {
if (portmsgbuf[0])
snprintf(tmp, sizeof(tmp), ",%u", ap[i]);
else
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
goto again;
}
}
if (strcmp(*modep, "LPRT") == 0) {
snprintf(tmp, sizeof(tmp), ",%d", plen);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf))
goto again;
}
for (i = 0; i < plen; i++) {
snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
goto again;
}
}
ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);
}
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if (nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if (ftpcode != 200) {
failf(data, "Server does not grok %s", *modep);
continue;
} else
break;
again:;
}
if (!*modep) {
close(portsock);
freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED;
}
#else
struct sockaddr_in sa;
struct hostent *h=NULL;
char *hostdataptr=NULL;
@@ -733,7 +912,7 @@ CURLcode _ftp(struct connectdata *conn)
/* we set the secondary socket variable to this for now, it
is only so that the cleanup function will close it in case
we fail before the true secondary stuff is made */
data->secondarysocket = portsock;
conn->secondarysocket = portsock;
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr,
@@ -795,13 +974,13 @@ CURLcode _ftp(struct connectdata *conn)
sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]);
#endif
ftpsendf(data->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d",
ftpsendf(conn->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d",
ip[0], ip[1], ip[2], ip[3],
porttouse >> 8,
porttouse & 255);
}
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -809,26 +988,43 @@ CURLcode _ftp(struct connectdata *conn)
failf(data, "Server does not grok PORT, try without it!");
return CURLE_FTP_PORT_FAILED;
}
#endif /* ENABLE_IPV6 */
}
else { /* we use the PASV command */
#if 0
char *mode[] = { "EPSV", "LPSV", "PASV", NULL };
int results[] = { 229, 228, 227, 0 };
#else
char *mode[] = { "PASV", NULL };
int results[] = { 227, 0 };
#endif
int modeoff;
ftpsendf(data->firstsocket, conn, "PASV");
for (modeoff = 0; mode[modeoff]; modeoff++) {
ftpsendf(conn->firstsocket, conn, mode[modeoff]);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if (ftpcode == results[modeoff])
break;
}
if(ftpcode != 227) {
if (!mode[modeoff]) {
failf(data, "Odd return code after PASV");
return CURLE_FTP_WEIRD_PASV_REPLY;
}
else {
else if (strcmp(mode[modeoff], "PASV") == 0) {
int ip[4];
int port[2];
unsigned short newport; /* remote port, not necessary the local one */
unsigned short connectport; /* the local port connect() should use! */
char newhost[32];
#ifdef ENABLE_IPV6
struct addrinfo *res;
#else
struct hostent *he;
#endif
char *str=buf,*ip_addr;
char *hostdataptr=NULL;
@@ -863,21 +1059,79 @@ CURLcode _ftp(struct connectdata *conn)
* proxy again here. We already have the name info for it since the
* previous lookup.
*/
#ifdef ENABLE_IPV6
res = conn->hp;
#else
he = conn->hp;
#endif
connectport =
(unsigned short)data->port; /* we connect to the proxy's port */
(unsigned short)conn->port; /* we connect to the proxy's port */
}
else {
/* normal, direct, ftp connection */
#ifdef ENABLE_IPV6
res = Curl_getaddrinfo(data, newhost, newport);
if(!res)
#else
he = Curl_gethost(data, newhost, &hostdataptr);
if(!he) {
if(!he)
#endif
{
failf(data, "Can't resolve new host %s", newhost);
return CURLE_FTP_CANT_GET_HOST;
}
connectport = newport; /* we connect to the remote port */
}
data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
conn->secondarysocket = -1;
for (ai = res; ai; ai = ai->ai_next) {
/* XXX for now, we can do IPv4 only */
if (ai->ai_family != AF_INET)
continue;
conn->secondarysocket = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (conn->secondarysocket < 0)
continue;
if(data->bits.verbose) {
char hbuf[NI_MAXHOST];
char nbuf[NI_MAXHOST];
char sbuf[NI_MAXSERV];
#ifdef NI_WITHSCOPEID
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
#else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif
if (getnameinfo(res->ai_addr, res->ai_addrlen, nbuf, sizeof(nbuf),
sbuf, sizeof(sbuf), niflags)) {
snprintf(nbuf, sizeof(nbuf), "?");
snprintf(sbuf, sizeof(sbuf), "?");
}
if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
NULL, 0, 0)) {
infof(data, "Connecting to %s port %s\n", nbuf, sbuf);
} else {
infof(data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf);
}
}
if (connect(conn->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) {
close(conn->secondarysocket);
conn->secondarysocket = -1;
continue;
}
break;
}
if (conn->secondarysocket < 0) {
failf(data, strerror(errno));
return CURLE_FTP_CANT_RECONNECT;
}
#else
conn->secondarysocket = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length);
@@ -951,7 +1205,7 @@ CURLcode _ftp(struct connectdata *conn)
if(hostdataptr)
free(hostdataptr);
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr,
if (connect(conn->secondarysocket, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
switch(errno) {
#ifdef ECONNREFUSED
@@ -962,7 +1216,7 @@ CURLcode _ftp(struct connectdata *conn)
#endif
#ifdef EINTR
case EINTR:
failf(data, "Connection timeouted to ftp server");
failf(data, "Connection timed out to ftp server");
break;
#endif
default:
@@ -971,14 +1225,17 @@ CURLcode _ftp(struct connectdata *conn)
}
return CURLE_FTP_CANT_RECONNECT;
}
#endif /*ENABLE_IPV6*/
if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->secondarysocket,
result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
newhost, newport);
if(CURLE_OK != result)
return result;
}
} else {
return CURLE_FTP_CANT_RECONNECT;
}
}
/* we have the (new) data connection ready */
@@ -987,10 +1244,10 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s",
ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1019,9 +1276,9 @@ CURLcode _ftp(struct connectdata *conn)
/* we could've got a specified offset from the command line,
but now we know we didn't */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1078,11 +1335,11 @@ CURLcode _ftp(struct connectdata *conn)
/* Send everything on data->in to the socket */
if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */
ftpsendf(data->firstsocket, conn, "APPE %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "APPE %s", ftp->file);
else
ftpsendf(data->firstsocket, conn, "STOR %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "STOR %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1093,7 +1350,7 @@ CURLcode _ftp(struct connectdata *conn)
}
if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock);
result = AllowServerConnect(data, conn, portsock);
if( result )
return result;
}
@@ -1106,7 +1363,7 @@ CURLcode _ftp(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, data->infilesize);
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp);
conn->secondarysocket, bytecountp);
if(result)
return result;
@@ -1138,16 +1395,16 @@ CURLcode _ftp(struct connectdata *conn)
else if(from < 0) {
/* -Y */
totalsize = -from;
data->maxdownload = -from;
conn->maxdownload = -from;
data->resume_from = from;
infof(data, "FTP RANGE the last %d bytes\n", totalsize);
}
else {
/* X-Y */
totalsize = to-from;
data->maxdownload = totalsize+1; /* include the last mentioned byte */
conn->maxdownload = totalsize+1; /* include the last mentioned byte */
data->resume_from = from;
infof(data, "FTP RANGE from %d getting %d bytes\n", from, data->maxdownload);
infof(data, "FTP RANGE from %d getting %d bytes\n", from, conn->maxdownload);
}
infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize);
@@ -1160,9 +1417,9 @@ CURLcode _ftp(struct connectdata *conn)
dirlist = TRUE;
/* Set type to ASCII */
ftpsendf(data->firstsocket, conn, "TYPE A");
ftpsendf(conn->firstsocket, conn, "TYPE A");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1175,16 +1432,16 @@ CURLcode _ftp(struct connectdata *conn)
better used since the LIST command output is not specified or
standard in any way */
ftpsendf(data->firstsocket, conn, "%s",
ftpsendf(conn->firstsocket, conn, "%s",
data->customrequest?data->customrequest:
(data->bits.ftp_list_only?"NLST":"LIST"));
}
else {
/* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s",
ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1203,9 +1460,9 @@ CURLcode _ftp(struct connectdata *conn)
* of the file we're gonna get. If we can get the size, this is by far
* the best way to know if we're trying to resume beyond the EOF. */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1247,9 +1504,9 @@ CURLcode _ftp(struct connectdata *conn)
infof(data, "Instructs server to resume from offset %d\n",
data->resume_from);
ftpsendf(data->firstsocket, conn, "REST %d", data->resume_from);
ftpsendf(conn->firstsocket, conn, "REST %d", data->resume_from);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1259,10 +1516,10 @@ CURLcode _ftp(struct connectdata *conn)
}
}
ftpsendf(data->firstsocket, conn, "RETR %s", ftp->file);
ftpsendf(conn->firstsocket, conn, "RETR %s", ftp->file);
}
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -1326,7 +1583,7 @@ CURLcode _ftp(struct connectdata *conn)
size = downloadsize;
if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock);
result = AllowServerConnect(data, conn, portsock);
if( result )
return result;
}
@@ -1334,7 +1591,7 @@ CURLcode _ftp(struct connectdata *conn)
infof(data, "Getting file with size: %d\n", size);
/* FTP download: */
result=Curl_Transfer(conn, data->secondarysocket, size, FALSE,
result=Curl_Transfer(conn, conn->secondarysocket, size, FALSE,
bytecountp,
-1, NULL); /* no upload here */
if(result)
@@ -1363,7 +1620,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
int dirlength=0; /* 0 forces strlen() */
/* the ftp struct is already inited in ftp_connect() */
ftp = data->proto.ftp;
ftp = conn->proto.ftp;
/* We split the path into dir and file parts *before* we URLdecode
it */
@@ -1452,3 +1709,16 @@ size_t Curl_ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
}
CURLcode Curl_ftp_disconnect(struct connectdata *conn)
{
struct FTP *ftp= conn->proto.ftp;
if(ftp->user)
free(ftp->user);
if(ftp->passwd)
free(ftp->passwd);
if(ftp->entrypath)
free(ftp->entrypath);
return CURLE_OK;
}

View File

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

View File

@@ -390,7 +390,7 @@ static const short yycheck[] = { 0,
56
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "/usr/local/share/bison.simple"
#line 3 "/usr/lib/bison.simple"
/* This file comes from bison-1.28. */
/* Skeleton output parser for bison,
@@ -604,7 +604,7 @@ __yy_memcpy (char *to, char *from, unsigned int count)
#endif
#endif
#line 217 "/usr/local/share/bison.simple"
#line 217 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
@@ -1295,7 +1295,7 @@ case 50:
break;}
}
/* the action file gets copied in in place of this dollarsign */
#line 543 "/usr/local/share/bison.simple"
#line 543 "/usr/lib/bison.simple"
yyvsp -= yylen;
yyssp -= yylen;

View File

@@ -1,28 +0,0 @@
#ifndef __GETENV_H
#define __GETENV_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#include <curl/curl.h>
#endif

View File

@@ -103,6 +103,12 @@ CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...)
case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->ssl.certverifyresult;
break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
*param_doublep = data->progress.size_dl;
break;
case CURLINFO_CONTENT_LENGTH_UPLOAD:
*param_doublep = data->progress.size_ul;
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}

View File

@@ -83,6 +83,29 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len)
return (addr);
}
#ifdef ENABLE_IPV6
struct addrinfo *Curl_getaddrinfo(struct UrlData *data,
char *hostname,
int port)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s\n", hostname);
return NULL;
}
return res;
}
#endif
/* The original code to this function was once stolen from the Dancer source
code, written by Bjorn Reese, it has since been patched and modified
considerably. */

View File

@@ -23,6 +23,11 @@
* $Id$
*****************************************************************************/
struct addrinfo;
struct addrinfo *Curl_getaddrinfo(struct UrlData *data,
char *hostname,
int port);
struct hostent *Curl_gethost(struct UrlData *data,
char *hostname,
char **bufp);

View File

@@ -214,7 +214,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
static
int GetLine(int sockfd, char *buf, struct connectdata *conn)
{
size_t nread;
ssize_t nread;
int read_rc=1;
char *ptr;
struct UrlData *data=conn->data;
@@ -226,17 +226,18 @@ int GetLine(int sockfd, char *buf, struct connectdata *conn)
(nread<BUFSIZE) && read_rc;
nread++, ptr++) {
if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) ||
(nread <= 0) ||
(*ptr == '\n'))
break;
}
*ptr=0; /* zero terminate */
if(data->bits.verbose) {
fputs("< ", data->err);
fwrite(buf, 1, nread, data->err);
fputs("\n", data->err);
}
return nread;
return nread>0?nread:0;
}
@@ -281,8 +282,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
"%s"
"\r\n",
hostname, remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"")
(data->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"",
(data->useragent?conn->allocptr.uagent:"")
);
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
@@ -324,21 +325,21 @@ CURLcode Curl_http_connect(struct connectdata *conn)
if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) {
/* HTTPS through a proxy can only be done with a tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket,
data->hostname, data->remote_port);
result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
conn->hostname, conn->remote_port);
if(CURLE_OK != result)
return result;
}
/* now, perform the SSL initialization for this socket */
if(Curl_SSLConnect(data))
if(Curl_SSLConnect(conn))
return CURLE_SSL_CONNECT_ERROR;
}
if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the
original host name */
data->auth_host = strdup(data->hostname);
data->auth_host = strdup(conn->hostname);
}
return CURLE_OK;
@@ -360,7 +361,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
struct HTTP *http;
data=conn->data;
http=data->proto.http;
http=conn->proto.http;
if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount;
@@ -374,9 +375,6 @@ CURLcode Curl_http_done(struct connectdata *conn)
*bytecount = http->readbytecount + http->writebytecount;
}
free(http);
data->proto.http=NULL; /* it is gone */
return CURLE_OK;
}
@@ -392,11 +390,17 @@ CURLcode Curl_http(struct connectdata *conn)
char *host = conn->name;
long *bytecount = &conn->bytecount;
http = (struct HTTP *)malloc(sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
data->proto.http = http;
if(!conn->proto.http) {
/* Only allocate this struct if we don't already have it! */
http = (struct HTTP *)malloc(sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
conn->proto.http = http;
}
else
http = conn->proto.http;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) {
@@ -407,9 +411,9 @@ CURLcode Curl_http(struct connectdata *conn)
have been used in the proxy connect, but if we have got a header with
the user-agent string specified, we erase the previously made string
here. */
if(checkheaders(data, "User-Agent:") && data->ptr_uagent) {
free(data->ptr_uagent);
data->ptr_uagent=NULL;
if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
free(conn->allocptr.uagent);
conn->allocptr.uagent=NULL;
}
if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
@@ -419,24 +423,27 @@ CURLcode Curl_http(struct connectdata *conn)
host due to a location-follow, we do some weirdo checks here */
if(!data->bits.this_is_a_follow ||
!data->auth_host ||
strequal(data->auth_host, data->hostname)) {
strequal(data->auth_host, conn->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd);
if(Curl_base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) {
data->ptr_userpwd = aprintf( "Authorization: Basic %s\015\012",
if(conn->allocptr.userpwd)
free(conn->allocptr.userpwd);
conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012",
authorization);
free(authorization);
}
}
}
if((data->bits.set_range) && !checkheaders(data, "Range:")) {
data->ptr_rangeline = aprintf("Range: bytes=%s\015\012", data->range);
}
if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) {
data->ptr_ref = aprintf("Referer: %s\015\012", data->referer);
if(conn->allocptr.ref)
free(conn->allocptr.ref);
conn->allocptr.ref = aprintf("Referer: %s\015\012", data->referer);
}
if(data->cookie && !checkheaders(data, "Cookie:")) {
data->ptr_cookie = aprintf("Cookie: %s\015\012", data->cookie);
if(conn->allocptr.cookie)
free(conn->allocptr.cookie);
conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->cookie);
}
if(data->cookies) {
@@ -455,14 +462,19 @@ CURLcode Curl_http(struct connectdata *conn)
http->sendit = Curl_getFormData(data->httppost, &http->postsize);
}
if(!checkheaders(data, "Host:")) {
if(((conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTPS)) ||
(!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) )
if(!checkheaders(data, "Host:") &&
!conn->allocptr.host) {
/* if ptr_host is already set, it is OK since we only re-use connections
to the very same host and port */
if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
(!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
/* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
the port number in the host string */
data->ptr_host = aprintf("Host: %s\r\n", host);
conn->allocptr.host = aprintf("Host: %s\r\n", host);
else
data->ptr_host = aprintf("Host: %s:%d\r\n", host, data->remote_port);
conn->allocptr.host = aprintf("Host: %s:%d\r\n", host,
conn->remote_port);
}
if(!checkheaders(data, "Pragma:"))
@@ -528,6 +540,34 @@ CURLcode Curl_http(struct connectdata *conn)
/* we've passed, proceed as normal */
}
}
if(data->bits.set_range) {
/*
* A range is selected. We use different headers whether we're downloading
* or uploading and we always let customized headers override our internal
* ones if any such are specified.
*/
if((data->httpreq == HTTPREQ_GET) &&
!checkheaders(data, "Range:")) {
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->range);
}
else if((data->httpreq != HTTPREQ_GET) &&
!checkheaders(data, "Content-Range:")) {
if(data->resume_from) {
/* This is because "resume" was selected */
long total_expected_size= data->resume_from + data->infilesize;
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n",
data->range, total_expected_size-1,
total_expected_size);
}
else {
/* Range was selected and then we just pass the incoming range and
append total size */
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n",
data->range, data->infilesize);
}
}
}
do {
send_buffer *req_buffer;
@@ -539,7 +579,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* add the main request stuff */
add_bufferf(req_buffer,
"%s " /* GET/HEAD/POST/PUT */
"%s HTTP/1.0\r\n" /* path */
"%s HTTP/1.1\r\n" /* path */
"%s" /* proxyuserpwd */
"%s" /* userpwd */
"%s" /* range */
@@ -555,15 +595,15 @@ CURLcode Curl_http(struct connectdata *conn)
(data->bits.http_post || data->bits.http_formpost)?"POST":
(data->bits.http_put)?"PUT":"GET"),
ppath,
(data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
(data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
(data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
(data->ptr_host?data->ptr_host:""), /* Host: host */
(data->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
(data->bits.user_passwd && conn->allocptr.userpwd)?conn->allocptr.userpwd:"",
(data->bits.set_range && conn->allocptr.rangeline)?conn->allocptr.rangeline:"",
(data->useragent && *data->useragent && conn->allocptr.uagent)?conn->allocptr.uagent:"",
(conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: <data> */
(conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
http->p_pragma?http->p_pragma:"",
http->p_accept?http->p_accept:"",
(data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
(data->bits.http_set_referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */
);
if(co) {
@@ -667,10 +707,10 @@ CURLcode Curl_http(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, http->postsize);
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE,
add_buffer_send(conn->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
conn->firstsocket,
&http->writebytecount);
if(result) {
Curl_FormFree(http->sendit); /* free that whole lot */
@@ -693,12 +733,12 @@ CURLcode Curl_http(struct connectdata *conn)
/* this sends the buffer and frees all the buffer resources */
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
add_buffer_send(conn->firstsocket, conn, req_buffer);
/* prepare for transfer */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE,
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
conn->firstsocket,
&http->writebytecount);
if(result)
return result;
@@ -739,10 +779,10 @@ CURLcode Curl_http(struct connectdata *conn)
/* issue the request */
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
add_buffer_send(conn->firstsocket, conn, req_buffer);
/* HTTP GET/HEAD download: */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */
}
if(result)

View File

@@ -24,7 +24,7 @@
*****************************************************************************/
#include "setup.h"
#if ! defined(WIN32) && ! defined(__BEOS__)
#if ! defined(WIN32) && ! defined(__BEOS__) && !defined(__CYGWIN32__)
extern char *Curl_if2ip(char *interface, char *buf, int buf_size);
#else
#define Curl_if2ip(a,b,c) NULL

View File

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

View File

@@ -171,10 +171,10 @@ CURLcode Curl_ldap(struct connectdata *conn)
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text);
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html);
server = ldap_open(data->hostname, data->port);
server = ldap_open(conn->hostname, conn->port);
if (server == NULL) {
failf(data, "LDAP: Cannot connect to %s:%d",
data->hostname, data->port);
conn->hostname, conn->port);
status = CURLE_COULDNT_CONNECT;
} else {
rc = ldap_simple_bind_s(server, data->user, data->passwd);

View File

@@ -2,7 +2,7 @@
; Definition file for the DLL version of the LIBCURL library from curl
;
LIBRARY LIBCURL
LIBRARY CURL
DESCRIPTION 'curl libcurl - http://curl.haxx.se'
@@ -32,11 +32,11 @@ EXPORTS
curl_unescape @ 23 ;
curl_version @ 24 ;
curl_write @ 25 ;
maprintf @ 26 ;
mfprintf @ 27 ;
mprintf @ 28 ;
msprintf @ 29 ;
msnprintf @ 30 ;
mvfprintf @ 31 ;
strequal @ 32 ;
strnequal @ 33 ;
curl_maprintf @ 26 ;
curl_mfprintf @ 27 ;
curl_mprintf @ 28 ;
curl_msprintf @ 29 ;
curl_msnprintf @ 30 ;
curl_mvfprintf @ 31 ;
Curl_strequal @ 32 ;
Curl_strnequal @ 33 ;

View File

@@ -72,7 +72,7 @@ void *curl_domalloc(size_t size, int line, char *source)
return mem;
}
char *curl_dostrdup(char *str, int line, char *source)
char *curl_dostrdup(const char *str, int line, char *source)
{
char *mem;
size_t len;

View File

@@ -7,7 +7,7 @@
void *curl_domalloc(size_t size, int line, char *source);
void *curl_dorealloc(void *ptr, size_t size, int line, char *source);
void curl_dofree(void *ptr, int line, char *source);
char *curl_dostrdup(char *str, int line, char *source);
char *curl_dostrdup(const char *str, int line, char *source);
void curl_memdebug(char *logname);
/* file descriptor manipulators */

View File

@@ -27,7 +27,8 @@
#include <stdlib.h>
#include <string.h>
#include "getenv.h"
#include <curl/curl.h>
#include "strequal.h"
/* Debug this single source file with:

View File

@@ -203,6 +203,9 @@ int Curl_pgrsUpdate(struct UrlData *data)
even when not displayed! */
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if (!data->progress.callback) {
if(data->resume_from)
fprintf(data->err, "** Resuming transfer from byte position %d\n",
data->resume_from);
fprintf(data->err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n");

View File

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

View File

@@ -50,6 +50,76 @@
#include "memdebug.h"
#endif
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
struct curl_slist *item;
/* if caller passed us a NULL, return now */
if (!list)
return NULL;
/* loop through to find the last item */
item = list;
while (item->next) {
item = item->next;
}
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list,
const char *data)
{
struct curl_slist *last;
struct curl_slist *new_item;
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
}
else {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL;
}
if (list) {
last = slist_get_last(list);
last->next = new_item;
return list;
}
/* if this is the first item, then new_item *is* the list */
return new_item;
}
/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
struct curl_slist *next;
struct curl_slist *item;
if (!list)
return;
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
free(item);
item = next;
} while (next);
}
/* infof() is for info message along the way */
void Curl_infof(struct UrlData *data, char *fmt, ...)
@@ -72,8 +142,11 @@ void Curl_failf(struct UrlData *data, char *fmt, ...)
va_start(ap, fmt);
if(data->errorbuffer)
vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap);
else /* no errorbuffer receives this, write to data->err instead */
else {
/* no errorbuffer receives this, write to data->err instead */
vfprintf(data->err, fmt, ap);
fprintf(data->err, "\n");
}
va_end(ap);
}
@@ -111,15 +184,14 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
size_t *written)
{
size_t bytes_written;
struct UrlData *data=conn->data; /* conn knows data, not vice versa */
#ifdef USE_SSLEAY
if (data->ssl.use) {
if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */
while(loop--) {
bytes_written = SSL_write(data->ssl.handle, mem, len);
bytes_written = SSL_write(conn->ssl.handle, mem, len);
if((-1 != bytes_written) ||
(SSL_ERROR_WANT_WRITE != SSL_get_error(data->ssl.handle,
(SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle,
bytes_written) ))
break;
}
@@ -198,18 +270,17 @@ CURLcode Curl_client_write(struct UrlData *data,
*/
CURLcode Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize,
size_t *n)
ssize_t *n)
{
struct UrlData *data = conn->data;
size_t nread;
ssize_t nread;
#ifdef USE_SSLEAY
if (data->ssl.use) {
if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */
while(loop--) {
nread = SSL_read(data->ssl.handle, buf, buffersize);
nread = SSL_read(conn->ssl.handle, buf, buffersize);
if((-1 != nread) ||
(SSL_ERROR_WANT_READ != SSL_get_error(data->ssl.handle, nread) ))
(SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) ))
break;
}
}
@@ -234,7 +305,7 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
*/
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
size_t *n)
ssize_t *n)
{
struct connectdata *conn = (struct connectdata *)c_conn;

View File

@@ -47,7 +47,7 @@ CURLcode Curl_client_write(struct UrlData *data, int type, char *ptr,
/* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize,
size_t *n);
ssize_t *n);
/* internal write-function, does plain socket, SSL and krb4 */
CURLcode Curl_write(struct connectdata *conn, int sockfd,
void *mem, size_t len,

View File

@@ -64,6 +64,7 @@ static int passwd_callback(char *buf, int num, int verify
static
int cert_stuff(struct UrlData *data,
struct connectdata *conn,
char *cert_file,
char *key_file)
{
@@ -78,10 +79,10 @@ int cert_stuff(struct UrlData *data,
*/
strcpy(global_passwd, data->cert_passwd);
/* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(data->ssl.ctx, passwd_callback);
SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
}
if (SSL_CTX_use_certificate_file(data->ssl.ctx,
if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file,
SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set certificate file (wrong password?)\n");
@@ -90,14 +91,14 @@ int cert_stuff(struct UrlData *data,
if (key_file == NULL)
key_file=cert_file;
if (SSL_CTX_use_PrivateKey_file(data->ssl.ctx,
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file,
SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set public key file\n");
return(0);
}
ssl=SSL_new(data->ssl.ctx);
ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl);
if (x509 != NULL)
@@ -111,7 +112,7 @@ int cert_stuff(struct UrlData *data,
/* Now we know that a key and cert have been set against
* the SSL context */
if (!SSL_CTX_check_private_key(data->ssl.ctx)) {
if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
failf(data, "Private key does not match the certificate public key\n");
return(0);
}
@@ -141,22 +142,23 @@ int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
/* ====================================================== */
int
Curl_SSLConnect (struct UrlData *data)
Curl_SSLConnect(struct connectdata *conn)
{
#ifdef USE_SSLEAY
int err;
char * str;
SSL_METHOD *req_method;
struct UrlData *data = conn->data;
int err;
char * str;
SSL_METHOD *req_method;
/* mark this is being ssl enabled from here on out. */
data->ssl.use = TRUE;
/* mark this is being ssl enabled from here on out. */
conn->ssl.use = TRUE;
/* Lets get nice error messages */
SSL_load_error_strings();
/* Lets get nice error messages */
SSL_load_error_strings();
#ifdef HAVE_RAND_STATUS
/* RAND_status() was introduced in OpenSSL 0.9.5 */
if(0 == RAND_status())
/* RAND_status() was introduced in OpenSSL 0.9.5 */
if(0 == RAND_status())
#endif
{
/* We need to seed the PRNG properly! */
@@ -177,116 +179,116 @@ Curl_SSLConnect (struct UrlData *data)
#endif
}
/* Setup all the global SSL stuff */
SSLeay_add_ssl_algorithms();
/* Setup all the global SSL stuff */
SSLeay_add_ssl_algorithms();
switch(data->ssl.version) {
default:
req_method = SSLv23_client_method();
break;
case 2:
req_method = SSLv2_client_method();
break;
case 3:
req_method = SSLv3_client_method();
break;
}
switch(data->ssl.version) {
default:
req_method = SSLv23_client_method();
break;
case 2:
req_method = SSLv2_client_method();
break;
case 3:
req_method = SSLv3_client_method();
break;
}
data->ssl.ctx = SSL_CTX_new(req_method);
conn->ssl.ctx = SSL_CTX_new(req_method);
if(!data->ssl.ctx) {
failf(data, "SSL: couldn't create a context!");
return 1;
}
if(!conn->ssl.ctx) {
failf(data, "SSL: couldn't create a context!");
return 1;
}
if(data->cert) {
if (!cert_stuff(data, data->cert, data->cert)) {
failf(data, "couldn't use certificate!\n");
return 2;
}
if(data->cert) {
if (!cert_stuff(data, conn, data->cert, data->cert)) {
failf(data, "couldn't use certificate!\n");
return 2;
}
}
if(data->ssl.verifypeer){
SSL_CTX_set_verify(data->ssl.ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
SSL_VERIFY_CLIENT_ONCE,
cert_verify_callback);
if (!SSL_CTX_load_verify_locations(data->ssl.ctx,
data->ssl.CAfile,
data->ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n");
return 2;
}
if(data->ssl.verifypeer){
SSL_CTX_set_verify(conn->ssl.ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
SSL_VERIFY_CLIENT_ONCE,
cert_verify_callback);
if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
data->ssl.CAfile,
data->ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n");
return 2;
}
else
SSL_CTX_set_verify(data->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
}
else
SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
/* Lets make an SSL structure */
data->ssl.handle = SSL_new (data->ssl.ctx);
SSL_set_connect_state (data->ssl.handle);
/* Lets make an SSL structure */
conn->ssl.handle = SSL_new (conn->ssl.ctx);
SSL_set_connect_state (conn->ssl.handle);
data->ssl.server_cert = 0x0;
conn->ssl.server_cert = 0x0;
/* pass the raw socket into the SSL layers */
SSL_set_fd (data->ssl.handle, data->firstsocket);
err = SSL_connect (data->ssl.handle);
/* pass the raw socket into the SSL layers */
SSL_set_fd (conn->ssl.handle, conn->firstsocket);
err = SSL_connect (conn->ssl.handle);
if (-1 == err) {
err = ERR_get_error();
failf(data, "SSL: %s", ERR_error_string(err, NULL));
return 10;
}
if (-1 == err) {
err = ERR_get_error();
failf(data, "SSL: %s", ERR_error_string(err, NULL));
return 10;
}
/* Informational message */
infof (data, "SSL connection using %s\n",
SSL_get_cipher(data->ssl.handle));
/* Informational message */
infof (data, "SSL connection using %s\n",
SSL_get_cipher(conn->ssl.handle));
/* Get server's certificate (note: beware of dynamic allocation) - opt */
/* major serious hack alert -- we should check certificates
* to authenticate the server; otherwise we risk man-in-the-middle
* attack
*/
/* Get server's certificate (note: beware of dynamic allocation) - opt */
/* major serious hack alert -- we should check certificates
* to authenticate the server; otherwise we risk man-in-the-middle
* attack
*/
data->ssl.server_cert = SSL_get_peer_certificate (data->ssl.handle);
if(!data->ssl.server_cert) {
failf(data, "SSL: couldn't get peer certificate!");
return 3;
}
infof (data, "Server certificate:\n");
conn->ssl.server_cert = SSL_get_peer_certificate (conn->ssl.handle);
if(!conn->ssl.server_cert) {
failf(data, "SSL: couldn't get peer certificate!");
return 3;
}
infof (data, "Server certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (data->ssl.server_cert),
NULL, 0);
if(!str) {
failf(data, "SSL: couldn't get X509-subject!");
return 4;
}
infof(data, "\t subject: %s\n", str);
CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_subject_name (conn->ssl.server_cert),
NULL, 0);
if(!str) {
failf(data, "SSL: couldn't get X509-subject!");
return 4;
}
infof(data, "\t subject: %s\n", str);
CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_issuer_name (data->ssl.server_cert),
NULL, 0);
if(!str) {
failf(data, "SSL: couldn't get X509-issuer name!");
return 5;
}
infof(data, "\t issuer: %s\n", str);
CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_issuer_name (conn->ssl.server_cert),
NULL, 0);
if(!str) {
failf(data, "SSL: couldn't get X509-issuer name!");
return 5;
}
infof(data, "\t issuer: %s\n", str);
CRYPTO_free(str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
if(data->ssl.verifypeer) {
data->ssl.certverifyresult=SSL_get_verify_result(data->ssl.handle);
infof(data, "Verify result: %d\n", data->ssl.certverifyresult);
}
else
data->ssl.certverifyresult=0;
if(data->ssl.verifypeer) {
data->ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
infof(data, "Verify result: %d\n", data->ssl.certverifyresult);
}
else
data->ssl.certverifyresult=0;
X509_free(data->ssl.server_cert);
X509_free(conn->ssl.server_cert);
#else /* USE_SSLEAY */
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void) data;
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void) data;
#endif
return 0;
return 0;
}

View File

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

View File

@@ -66,3 +66,44 @@ int Curl_strnequal(const char *first, const char *second, size_t max)
#endif
}
#ifndef HAVE_STRLCAT
/*
* The strlcat() function appends the NUL-terminated string src to the end
* of dst. It will append at most size - strlen(dst) - 1 bytes, NUL-termi-
* nating the result.
*
* The strlcpy() and strlcat() functions return the total length of the
* string they tried to create. For strlcpy() that means the length of src.
* For strlcat() that means the initial length of dst plus the length of
* src. While this may seem somewhat confusing it was done to make trunca-
* tion detection simple.
*
*
*/
size_t strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -82,7 +82,6 @@
#include <curl/types.h>
#include "netrc.h"
#include "getenv.h"
#include "hostip.h"
#include "transfer.h"
#include "sendf.h"
@@ -109,7 +108,7 @@
CURLcode static
_Transfer(struct connectdata *c_conn)
{
size_t nread; /* number of bytes read */
ssize_t nread; /* number of bytes read */
int bytecount = 0; /* total number of bytes read */
int writebytecount = 0; /* number of bytes written */
long contentlength=0; /* size of incoming data */
@@ -128,6 +127,7 @@ _Transfer(struct connectdata *c_conn)
int offset = 0; /* possible resume offset read from the
Content-Range: header */
int code = 0; /* error code from the 'HTTP/1.? XXX' line */
int httpversion = -1; /* the last digit in the HTTP/1.1 string */
/* for the low speed checks: */
CURLcode urg;
@@ -161,6 +161,12 @@ _Transfer(struct connectdata *c_conn)
Curl_pgrsTime(data, TIMER_PRETRANSFER);
Curl_speedinit(data);
if((conn->sockfd == -1) &&
(conn->writesockfd == -1)) {
/* nothing to read, nothing to write, we're already OK! */
return CURLE_OK;
}
if (!conn->getheader) {
header = FALSE;
if(conn->size > 0)
@@ -314,9 +320,9 @@ _Transfer(struct connectdata *c_conn)
p++; /* pass the \r byte */
if ('\n' == *p)
p++; /* pass the \n byte */
#if 0 /* headers are not included in the size */
Curl_pgrsSetDownloadSize(data, conn->size);
#endif
header = FALSE; /* no more header to parse! */
/* now, only output this if the header AND body are requested:
@@ -337,7 +343,7 @@ _Transfer(struct connectdata *c_conn)
if (!headerline++) {
/* This is the first header, it MUST be the error code line
or else we consiser this to be the body right away! */
if (sscanf (p, " HTTP/1.%*c %3d", &code)) {
if (2 == sscanf (p, " HTTP/1.%d %3d", &httpversion, &code)) {
/* 404 -> URL not found! */
if (
( ((data->bits.http_follow_location) && (code >= 400))
@@ -361,6 +367,16 @@ _Transfer(struct connectdata *c_conn)
if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength))
conn->size = contentlength;
else if (strnequal("Connection: close", p,
strlen("Connection: close"))) {
/*
* [RFC 2616, section 8.1.2.1]
* "Connection: close" is HTTP/1.1 language and means that
* the connection will close when this request has been
* served.
*/
conn->bits.close = TRUE; /* close when done */
}
else if (strnequal("Content-Range", p, 13)) {
if (sscanf (p+13, ": bytes %d-", &offset) ||
sscanf (p+13, ": bytes: %d-", &offset)) {
@@ -444,9 +460,14 @@ _Transfer(struct connectdata *c_conn)
write a chunk of the body */
if(conn->protocol&PROT_HTTP) {
/* HTTP-only checks */
if (data->resume_from &&
!content_range &&
(data->httpreq==HTTPREQ_GET)) {
if (data->newurl) {
/* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl);
return CURLE_OK;
}
else if (data->resume_from &&
!content_range &&
(data->httpreq==HTTPREQ_GET)) {
/* we wanted to resume a download, although the server
doesn't seem to support this and we did this with a GET
(if it wasn't a GET we did a POST or PUT resume) */
@@ -454,11 +475,6 @@ _Transfer(struct connectdata *c_conn)
"byte ranges. Cannot resume.");
return CURLE_HTTP_RANGE_ERROR;
}
else if (data->newurl) {
/* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl);
return CURLE_OK;
}
else if(data->timecondition && !data->range) {
/* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of
@@ -484,13 +500,23 @@ _Transfer(struct connectdata *c_conn)
} /* switch */
} /* two valid time strings */
} /* we have a time condition */
if(!conn->bits.close && (httpversion == 1)) {
/* If this is not the last request before a close, we must
set the maximum download size to the size of the expected
document or else, we won't know when to stop reading! */
if(-1 != conn->size)
conn->maxdownload = conn->size;
/* What to do if the size is *not* known? */
}
} /* this is HTTP */
} /* this is the first time we write a body part */
bodywrites++;
if(data->maxdownload &&
(bytecount + nread > data->maxdownload)) {
nread = data->maxdownload - bytecount;
if(conn->maxdownload &&
(bytecount + nread >= conn->maxdownload)) {
nread = conn->maxdownload - bytecount;
if((signed int)nread < 0 ) /* this should be unusual */
nread = 0;
keepon &= ~KEEP_READ; /* we're done reading */
@@ -606,12 +632,13 @@ CURLcode curl_transfer(CURL *curl)
CURLcode res;
struct UrlData *data = curl;
struct connectdata *c_connect=NULL;
bool port=TRUE; /* allow data->use_port to set port to use */
Curl_pgrsStartNow(data);
do {
Curl_pgrsTime(data, TIMER_STARTSINGLE);
res = curl_connect(curl, (CURLconnect **)&c_connect);
res = curl_connect(curl, (CURLconnect **)&c_connect, port);
if(res == CURLE_OK) {
res = curl_do(c_connect);
if(res == CURLE_OK) {
@@ -628,9 +655,14 @@ CURLcode curl_transfer(CURL *curl)
char prot[16]; /* URL protocol string storage */
char letter; /* used for a silly sscanf */
port=TRUE; /* by default we use the user set port number even after
a Location: */
if (data->maxredirs && (data->followlocation >= data->maxredirs)) {
failf(data,"Maximum (%d) redirects followed", data->maxredirs);
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect);
#endif
res=CURLE_TOO_MANY_REDIRECTS;
break;
}
@@ -673,9 +705,10 @@ CURLcode curl_transfer(CURL *curl)
if(!protsep)
protsep=data->url;
else {
/* TBD: set the port with curl_setopt() */
data->port=0; /* we got a full URL and then we should reset the
port number here to re-initiate it later */
port=FALSE; /* we got a full URL and thus we should not obey the
port number that might have been set by the user
in data->use_port */
protsep+=2; /* pass the slashes */
}
@@ -712,9 +745,8 @@ CURLcode curl_transfer(CURL *curl)
data->newurl = newest;
}
else {
/* This was an absolute URL, clear the port number! */
/* TBD: set the port with curl_setopt() */
data->port = 0;
/* This is an absolute URL, don't use the custom port number */
port = FALSE;
}
if(data->bits.urlstringalloc)
@@ -725,18 +757,57 @@ CURLcode curl_transfer(CURL *curl)
data->newurl = NULL; /* don't show! */
data->bits.urlstringalloc = TRUE; /* the URL is allocated */
/* Disable both types of POSTs, since doing a second POST when
following isn't what anyone would want! */
data->bits.http_post = FALSE;
data->bits.http_formpost = FALSE;
infof(data, "Follows Location: to new URL: '%s'\n", data->url);
/*
* We get here when the HTTP code is 300-399. We need to perform
* differently based on exactly what return code there was.
* Discussed on the curl mailing list and posted about on the 26th
* of January 2001.
*/
switch(data->progress.httpcode) {
case 300: /* Multiple Choices */
case 301: /* Moved Permanently */
case 302: /* Found */
case 306: /* Not used */
case 307: /* Temporary Redirect */
default: /* for all unknown ones */
/* These are explicitly mention since I've checked RFC2616 and they
* seem to be OK to POST to.
*/
break;
case 303: /* See Other */
/* Disable both types of POSTs, since doing a second POST when
* following isn't what anyone would want! */
data->bits.http_post = FALSE;
data->bits.http_formpost = FALSE;
data->httpreq = HTTPREQ_GET; /* enfore GET request */
infof(data, "Disables POST\n");
break;
case 304: /* Not Modified */
/* 304 means we did a conditional request and it was "Not modified".
* We shouldn't get any Location: header in this response!
*/
break;
case 305: /* Use Proxy */
/* (quote from RFC2616, section 10.3.6):
* "The requested resource MUST be accessed through the proxy given
* by the Location field. The Location field gives the URI of the
* proxy. The recipient is expected to repeat this single request
* via the proxy. 305 responses MUST only be generated by origin
* servers."
*/
break;
}
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect);
#endif
continue;
}
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect);
#endif
}
break; /* it only reaches here when this shouldn't loop */

1099
lib/url.c

File diff suppressed because it is too large Load Diff

View File

@@ -133,6 +133,64 @@ enum protection_level {
};
#endif
/* struct for data related to SSL and SSL connections */
struct ssl_connect_data {
bool use; /* use ssl encrypted communications TRUE/FALSE */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
struct ssl_config_data {
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
};
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
char *entrypath; /* the PWD reply when we logged on */
};
/*
* Boolean values that concerns this connection.
*/
struct ConnectBits {
bool close; /* if set, we close the connection after this request */
bool reuse; /* if set, this is a re-used connection */
};
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
@@ -145,6 +203,9 @@ struct connectdata {
Handle handle; /* struct identifier */
struct UrlData *data; /* link to the root CURL struct */
int connectindex; /* what index in the connects index this particular
struct has */
/**** curl_connect() phase fields */
ConnState state; /* for state dependent actions */
@@ -159,20 +220,38 @@ struct connectdata {
#define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8)
#ifdef ENABLE_IPV6
struct addrinfo *hp; /* host info pointer list */
struct addrinfo *ai; /* the particular host we use */
#else
char *hostent_buf; /* pointer to allocated memory for name info */
struct hostent *hp;
struct sockaddr_in serv_addr;
char proto[64]; /* store the protocol string in this buffer */
#endif
char protostr[64]; /* store the protocol string in this buffer */
char gname[257]; /* store the hostname in this buffer */
char *name; /* host name pointer to fool around with */
char *path; /* allocated buffer to store the URL's path part in */
char *hostname; /* hostname to connect, as parsed from url */
long port; /* which port to use locally */
unsigned short remote_port; /* what remote port to connect to,
not the proxy port! */
char *ppath;
long bytecount;
struct timeval now; /* current time */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE
never smaller than UPLOAD_BUFSIZE */
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */
struct ssl_connect_data ssl; /* this is for ssl-stuff */
struct ConnectBits bits; /* various state-flags for this connection */
/* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect);
@@ -183,6 +262,11 @@ struct connectdata {
*/
CURLcode (*curl_connect)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection.
*/
CURLcode (*curl_disconnect)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run
* in the curl_close() function if protocol-specific cleanups are required.
*/
@@ -201,6 +285,18 @@ struct connectdata {
the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */
/** Dynamicly allocated strings, may need to be freed before this **/
/** struct is killed. **/
struct dynamically_allocated_data {
char *proxyuserpwd; /* free later if not NULL! */
char *uagent; /* free later if not NULL! */
char *userpwd; /* free later if not NULL! */
char *rangeline; /* free later if not NULL! */
char *ref; /* free later if not NULL! */
char *cookie; /* free later if not NULL! */
char *host; /* free later if not NULL */
} allocptr;
#ifdef KRB4
enum protection_level command_prot;
@@ -214,6 +310,24 @@ struct connectdata {
void *app_data;
#endif
/*************** Request - specific items ************/
/* previously this was in the urldata struct */
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
};
struct Progress {
@@ -249,35 +363,6 @@ struct Progress {
int speeder_c;
};
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
};
typedef enum {
HTTPREQ_NONE, /* first in list */
HTTPREQ_GET,
@@ -334,22 +419,6 @@ typedef enum {
CURLI_LAST
} CurlInterface;
/* struct for data related to SSL and SSL connections */
struct ssldata {
bool use; /* use ssl encrypted communications TRUE/FALSE */
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
/*
* As of April 11, 2000 we're now trying to split up the urldata struct in
* three different parts:
@@ -364,8 +433,15 @@ struct ssldata {
*
* (Request)
* 3 - Request-specific. Variables that are of interest for this particular
* transfer being made right now.
* transfer being made right now. THIS IS WRONG STRUCT FOR THOSE.
*
* In Febrary 2001, this is being done stricter. The 'connectdata' struct
* MUST have all the connection oriented stuff as we may now have several
* simultaneous connections and connection structs in memory.
*
* From now on, the 'UrlData' must only contain data that is set once to go
* for many (perhaps) independent connections. Values that are generated or
* calculated internally MUST NOT be a part of this struct.
*/
struct UrlData {
@@ -377,7 +453,7 @@ struct UrlData {
char *errorbuffer; /* store failure messages in here */
/*************** Session - specific items ************/
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */
char *proxy; /* if proxy, set it here */
char *proxyuserpwd; /* Proxy <user:password>, if used */
long proxyport; /* If non-zero, use this port number by default. If the
proxy string features a ":[port]" that one will override
@@ -387,33 +463,14 @@ struct UrlData {
long header_size; /* size of read header(s) in bytes */
long request_size; /* the amount of bytes sent in the request(s) */
/*************** Request - specific items ************/
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
FILE *out; /* the fetched file goes here */
FILE *in; /* the uploaded file is read from here */
FILE *writeheader; /* write the header to this is non-NULL */
char *url; /* what to get */
char *freethis; /* if non-NULL, an allocated string for the URL */
char *hostname; /* hostname to connect, as parsed from url */
long port; /* which port to use (if non-protocol bind) set
CONF_PORT to use this */
unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */
long use_port; /* which port to use (when not using default) */
struct Configbits bits; /* new-style (v7) flag data */
struct ssl_config_data ssl; /* this is for ssl-stuff */
char *userpwd; /* <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on
@@ -455,13 +512,6 @@ struct UrlData {
long timeout; /* in seconds, 0 means no timeout */
long infilesize; /* size of file to upload, -1 means unknown */
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */
/* fields only set and used within _urlget() */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */
double current_speed; /* the ProgressShow() funcion sets this */
@@ -484,12 +534,13 @@ struct UrlData {
struct CookieInfo *cookies;
struct ssldata ssl; /* this is for ssl-stuff */
long crlf;
struct curl_slist *quote; /* before the transfer */
struct curl_slist *postquote; /* after the transfer */
/* Telnet negotiation options */
struct curl_slist *telnet_options; /* linked list of telnet options */
TimeCond timecondition; /* kind of comparison */
time_t timevalue; /* what time to compare with */
@@ -500,12 +551,6 @@ struct UrlData {
char *headerbuff; /* allocated buffer to store headers in */
int headersize; /* size of the allocation */
#if 0
/* this was removed in libcurl 7.4 */
char *writeinfo; /* if non-NULL describes what to output on a successful
completion */
#endif
struct Progress progress; /* for all the progress meter data */
#define MAX_CURL_USER_LENGTH 128
@@ -522,25 +567,209 @@ struct UrlData {
char proxyuser[MAX_CURL_USER_LENGTH];
char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
/**** Dynamicly allocated strings, may need to be freed on return ****/
char *ptr_proxyuserpwd; /* free later if not NULL! */
char *ptr_uagent; /* free later if not NULL! */
char *ptr_userpwd; /* free later if not NULL! */
char *ptr_rangeline; /* free later if not NULL! */
char *ptr_ref; /* free later if not NULL! */
char *ptr_cookie; /* free later if not NULL! */
char *ptr_host; /* free later if not NULL */
char *krb4_level; /* what security level */
#ifdef KRB4
FILE *cmdchannel;
#endif
struct timeval keeps_speed; /* this should be request-specific */
/* 'connects' will be an allocated array with pointers. If the pointer is
set, it holds an allocated connection. */
struct connectdata **connects;
size_t numconnects; /* size of the 'connects' array */
curl_closepolicy closepolicy;
};
#define LIBCURL_NAME "libcurl"
#define LIBCURL_ID LIBCURL_NAME " " LIBCURL_VERSION " " SSL_ID
/*
* Here follows function prototypes from what we used to plan to call
* the "low level" interface. It is no longer prioritized and it is not likely
* to ever be supported to external users.
*/
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Inits libcurl globally. This must be used before any libcurl calls can
* be used. This may install global plug-ins or whatever. (This does not
* do winsock inits in Windows.)
*
* EXAMPLE
*
* curl_init();
*
*/
CURLcode curl_init(void);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Frees libcurl globally. This must be used after all libcurl calls have
* been used. This may remove global plug-ins or whatever. (This does not
* do winsock cleanups in Windows.)
*
* EXAMPLE
*
* curl_free(curl);
*
*/
void curl_free(void);
/*
* NAME curl_open()
*
* DESCRIPTION
*
* Opens a general curl session. It does not try to connect or do anything
* on the network because of this call. The specified URL is only required
* to enable curl to figure out what protocol to "activate".
*
* A session should be looked upon as a series of requests to a single host. A
* session interacts with one host only, using one single protocol.
*
* The URL is not required. If set to "" or NULL, it can still be set later
* using the curl_setopt() function. If the curl_connect() function is called
* without the URL being known, it will return error.
*
* EXAMPLE
*
* CURLcode result;
* CURL *curl;
* result = curl_open(&curl, "http://curl.haxx.nu/libcurl/");
* if(result != CURL_OK) {
* return result;
* }
* */
CURLcode curl_open(CURL **curl, char *url);
/*
* NAME curl_setopt()
*
* DESCRIPTION
*
* Sets a particular option to the specified value.
*
* EXAMPLE
*
* CURL curl;
* curl_setopt(curl, CURL_HTTP_FOLLOW_LOCATION, TRUE);
*/
CURLcode curl_setopt(CURL *handle, CURLoption option, ...);
/*
* NAME curl_close()
*
* DESCRIPTION
*
* Closes a session previously opened with curl_open()
*
* EXAMPLE
*
* CURL *curl;
* CURLcode result;
*
* result = curl_close(curl);
*/
CURLcode curl_close(CURL *curl); /* the opposite of curl_open() */
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
ssize_t *n);
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n);
/*
* NAME curl_connect()
*
* DESCRIPTION
*
* Connects to the peer server and performs the initial setup. This function
* writes a connect handle to its second argument that is a unique handle for
* this connect. This allows multiple connects from the same handle returned
* by curl_open().
*
* By setting 'allow_port' to FALSE, the data->use_port will *NOT* be
* respected.
*
* EXAMPLE
*
* CURLCode result;
* CURL curl;
* CURLconnect connect;
* result = curl_connect(curl, &connect); */
CURLcode curl_connect(CURL *curl,
CURLconnect **in_connect,
bool allow_port);
/*
* NAME curl_do()
*
* DESCRIPTION
*
* (Note: May 3rd 2000: this function does not currently allow you to
* specify a document, it will use the one set previously)
*
* This function asks for the particular document, file or resource that
* resides on the server we have connected to. You may specify a full URL,
* just an absolute path or even a relative path. That means, if you're just
* getting one file from the remote site, you can use the same URL as input
* for both curl_open() as well as for this function.
*
* In the even there is a host name, port number, user name or password parts
* in the URL, you can use the 'flags' argument to ignore them completely, or
* at your choice, make the function fail if you're trying to get a URL from
* different host than you connected to with curl_connect().
*
* You can only get one document at a time using the same connection. When one
* document has been received you can although request again.
*
* When the transfer is done, curl_done() MUST be called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_do(connect, url, CURL_DO_NONE); */
CURLcode curl_do(CURLconnect *in_conn);
/*
* NAME curl_done()
*
* DESCRIPTION
*
* When the transfer following a curl_do() call is done, this function should
* get called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_done(connect); */
CURLcode curl_done(CURLconnect *connect);
/*
* NAME curl_disconnect()
*
* DESCRIPTION
*
* Disconnects from the peer server and performs connection cleanup.
*
* EXAMPLE
*
* CURLcode result;
* CURLconnect *connect;
* result = curl_disconnect(connect); */
CURLcode curl_disconnect(CURLconnect *connect);
#endif

View File

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

View File

@@ -17,7 +17,7 @@ LINKR = link.exe /incremental:no /libpath:"../lib"
## Debug
CCD = cl.exe /MDd /Gm /ZI /Od /D "_DEBUG" /GZ
LINKD = link.exe /incremental:yes /debug
LINKD = link.exe /incremental:yes /debug /libpath:"../lib"
CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
LFLAGS = /nologo /out:$(PROGRAM_NAME) /subsystem:console /machine:I386

View File

@@ -102,14 +102,13 @@ typedef enum {
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
#define CONF_UPLOAD (1<<14) /* this is an upload */
#define CONF_POST (1<<15) /* HTTP POST method */
#define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
#define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */
#define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */
#define CONF_PUT (1<<27) /* PUT the input file */
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
#ifndef HAVE_STRDUP
@@ -277,6 +276,7 @@ static void help(void)
" -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n"
" -s/--silent Silent mode. Don't output anything\n"
" -S/--show-error Show error. With -s, make curl show errors when they occur\n"
" -t/--telnet-option <OPT=val> Set telnet option\n"
" -T/--upload-file <file> Transfer/upload <file> to remote site\n"
" --url <URL> Another way to specify URL to work with\n"
" -u/--user <user[:password]> Specify user and password to use\n"
@@ -364,6 +364,8 @@ struct Configurable {
struct HttpPost *httppost;
struct HttpPost *last_post;
struct curl_slist *telnet_options;
HttpReq httpreq;
};
@@ -563,7 +565,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"r", "range", TRUE},
{"s", "silent", FALSE},
{"S", "show-error", FALSE},
{"t", "upload", FALSE},
{"t", "telnet-options", TRUE},
{"T", "upload-file", TRUE},
{"u", "user", TRUE},
{"U", "proxy-user", TRUE},
@@ -783,8 +785,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
else
config->postfields=postdata;
}
if(config->postfields)
config->conf |= CONF_POST;
if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
return PARAM_BAD_USE;
break;
@@ -957,9 +958,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
config->showerror ^= TRUE; /* toggle on if used with -s */
break;
case 't':
/* we are uploading */
config->conf ^= CONF_UPLOAD;
fprintf(stderr, "-t is a deprecated switch, use '-T -' instead!\n");
/* Telnet options */
config->telnet_options = curl_slist_append(config->telnet_options, nextarg);
break;
case 'T':
/* we are uploading */
@@ -1741,7 +1741,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FAILONERROR,
config->conf&CONF_FAILONERROR);
curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD);
curl_easy_setopt(curl, CURLOPT_POST, config->conf&CONF_POST);
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
config->conf&CONF_FTPLISTONLY);
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
@@ -1749,7 +1748,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
config->conf&CONF_FOLLOWLOCATION);
curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
curl_easy_setopt(curl, CURLOPT_PUT, config->conf&CONF_PUT);
curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
@@ -1820,6 +1818,9 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
}
/* new in libcurl 7.6.2: */
curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
res = curl_easy_perform(curl);
if(config->writeout) {

View File

@@ -1,3 +1,3 @@
#define CURL_NAME "curl"
#define CURL_VERSION "7.6"
#define CURL_VERSION "7.7-alpha2"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "

View File

@@ -56,4 +56,10 @@ command26.txt prot26.txt command27.txt prot27.txt \
name26.txt reply26.txt name27.txt stdout27.txt \
command28.txt name28.txt prot28.txt reply28.txt \
command120.txt name120.txt prot120.txt reply120.txt \
command121.txt name121.txt prot121.txt reply121.txt
command121.txt name121.txt prot121.txt reply121.txt \
command29.txt error30.txt name30.txt prot30.txt reply30.txt \
command30.txt name29.txt prot29.txt reply29.txt \
command31.txt name32.txt reply31.txt reply32.txt \
command32.txt prot31.txt reply310001.txt reply320001.txt \
name31.txt prot32.txt reply310002.txt reply320002.txt \
command33.txt extra33.txt name33.txt prot33.txt reply33.txt

1
tests/data/command29.txt Normal file
View File

@@ -0,0 +1 @@
-C 200 http://%HOSTIP:%HOSTPORT/29

1
tests/data/command30.txt Normal file
View File

@@ -0,0 +1 @@
http://%HOSTIP:%HOSTPORT/30

2
tests/data/command31.txt Normal file
View File

@@ -0,0 +1,2 @@
http://%HOSTIP:%HOSTPORT/31 -d mooo=fooo -L

2
tests/data/command32.txt Normal file
View File

@@ -0,0 +1,2 @@
http://%HOSTIP:%HOSTPORT/32 -d mooo=fooo -L

3
tests/data/command33.txt Normal file
View File

@@ -0,0 +1,3 @@
http://%HOSTIP:%HOSTPORT/33 -Tdata/extra33.txt -C 50

1
tests/data/error30.txt Normal file
View File

@@ -0,0 +1 @@
18

15
tests/data/extra33.txt Normal file
View File

@@ -0,0 +1,15 @@
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678

1
tests/data/name29.txt Normal file
View File

@@ -0,0 +1 @@
HTTP download resume with Content-Length validity

1
tests/data/name30.txt Normal file
View File

@@ -0,0 +1 @@
HTTP GET uncomplete document

1
tests/data/name31.txt Normal file
View File

@@ -0,0 +1 @@
HTTP POST and follow Location: (error 301)

1
tests/data/name32.txt Normal file
View File

@@ -0,0 +1 @@
HTTP POST and follow Location: (error 303)

1
tests/data/name33.txt Normal file
View File

@@ -0,0 +1 @@
HTTP PUT resume

7
tests/data/prot29.txt Normal file
View File

@@ -0,0 +1,7 @@
GET /29 HTTP/1.0
Range: bytes=200-
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

6
tests/data/prot30.txt Normal file
View File

@@ -0,0 +1,6 @@
GET /30 HTTP/1.0
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

9
tests/data/prot31.txt Normal file
View File

@@ -0,0 +1,9 @@
POST /moo/moo/moo/310002 HTTP/1.0
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
mooo=fooo

6
tests/data/prot32.txt Normal file
View File

@@ -0,0 +1,6 @@
GET /moo/moo/moo/320002 HTTP/1.0
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

18
tests/data/prot33.txt Normal file
View File

@@ -0,0 +1,18 @@
PUT /33 HTTP/1.0
Content-Range: bytes 50-149/150
User-Agent: curl/7.6 (sparc-sun-solaris2.7) libcurl 7.6-pre4 (SSL 0.9.6) (krb4 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Content-Length: 100
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678

View File

@@ -2,5 +2,6 @@ HTTP/1.1 301 This is a weirdo text message
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Location: data/110002.txt?coolsite=yes
Connection: close
This server reply is for testing a simple Location: following

View File

@@ -2,6 +2,7 @@ HTTP/1.1 301 This is a weirdo text message
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Location: data/110002.txt?coolsite=yes
Connection: close
HTTP/1.1 200 Followed here fine
Date: Thu, 09 Nov 2010 14:49:00 GMT

9
tests/data/reply29.txt Normal file
View File

@@ -0,0 +1,9 @@
HTTP/1.1 200 OK
Server: fake
Content-Range: bytes 200-3526/3527
Content-Length: 84
The Content-Range header's contents above aren't really genuine for this
content.

7
tests/data/reply30.txt Normal file
View File

@@ -0,0 +1,7 @@
HTTP/1.1 200 OK
Server: fake
Content-Length: 8400
This file is a lot smaller than 8400 and thus curl should return an error
for this.

6
tests/data/reply31.txt Normal file
View File

@@ -0,0 +1,6 @@
HTTP/1.1 301 Moved Permanently
Server: fake
Location: /moo/moo/moo/310002
No contents

View File

@@ -0,0 +1,9 @@
HTTP/1.1 301 Moved Permanently
Server: fake
Location: /moo/moo/moo/310002
HTTP/1.1 200 Followed here fine
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
If this is received, the location following worked

View File

@@ -0,0 +1,5 @@
HTTP/1.1 200 Followed here fine
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
If this is received, the location following worked

7
tests/data/reply32.txt Normal file
View File

@@ -0,0 +1,7 @@
HTTP/1.1 303 See Other
Server: fake
Location: /moo/moo/moo/320002
This Location should be fetched with a GET!

View File

@@ -0,0 +1,9 @@
HTTP/1.1 303 See Other
Server: fake
Location: /moo/moo/moo/320002
HTTP/1.1 200 Followed here fine
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
If this is received, the location following worked

View File

@@ -0,0 +1,5 @@
HTTP/1.1 200 Followed here fine
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
If this is received, the location following worked

7
tests/data/reply33.txt Normal file
View File

@@ -0,0 +1,7 @@
HTTP/1.1 303 See Other
Server: fake
Location: /moo/moo/moo/320002
This Location should be fetched with a GET!

View File

@@ -119,7 +119,7 @@ for ( $waitedpid = 0;
$testnum=$1;
if($verbose) {
print STDERR "sending reply $testnum\n";
print STDERR "OUT: sending reply $testnum\n";
}
}
else {

View File

@@ -49,7 +49,9 @@ my $memanalyze="../memanalyze.pl";
my $short;
my $verbose;
my $debugprotocol;
my $anyway;
my $gdbthis; # run test case with gdb debugger
#######################################################################
# Return the pid of the server as found in the given pid file
@@ -109,7 +111,8 @@ sub runhttpserver {
}
if ($RUNNING != 1) {
system("perl $srcdir/httpserver.pl $HOSTPORT &");
my $flag=$debugprotocol?"-v ":"";
system("perl $srcdir/httpserver.pl $flag $HOSTPORT &");
sleep 1; # give it a little time to start
}
else {
@@ -150,7 +153,8 @@ sub runftpserver {
}
if ($RUNNING != 1) {
system("perl $srcdir/ftpserver.pl $FTPPORT &");
my $flag=$debugprotocol?"-v ":"";
system("perl $srcdir/ftpserver.pl $flag $FTPPORT &");
sleep 1; # give it a little time to start
}
else {
@@ -394,12 +398,13 @@ sub singletest {
}
# run curl, add -v for debug information output
my $CMDLINE="$CURL $out--include -v --silent $cmd >$STDOUT 2>$STDERR";
my $cmdargs="$out--include -v --silent $cmd";
my $STDINFILE="$TESTDIR/stdin$NUMBER.txt";
if(-f $STDINFILE) {
$CMDLINE .= " < $STDINFILE";
$cmdargs .= " < $STDINFILE";
}
my $CMDLINE="$CURL $cmdargs >$STDOUT 2>$STDERR";
if($verbose) {
print "$CMDLINE\n";
@@ -407,9 +412,20 @@ sub singletest {
print CMDLOG "$CMDLINE\n";
my $res;
# run the command line we built
my $res = system("$CMDLINE");
$res /= 256;
if($gdbthis) {
open(GDBCMD, ">log/gdbcmd");
print GDBCMD "set args $cmdargs\n";
print GDBCMD "show args\n";
close(GDBCMD);
system("gdb $CURL -x log/gdbcmd");
$res =0; # makes it always continue after a debugged run
}
else {
$res = system("$CMDLINE");
$res /= 256;
}
my $ERRORCODE = "$TESTDIR/error$NUMBER.txt";
@@ -504,6 +520,8 @@ sub singletest {
unlink($STDOUT);
unlink($STDERR);
unlink("$LOGDIR/upload.$NUMBER"); # remove upload leftovers
unlink($CURLOUT); # remove the downloaded results
unlink($FTPDCMD); # remove the instructions for this test
if($memory_debug) {
@@ -551,6 +569,14 @@ do {
# verbose output
$verbose=1;
}
elsif ($ARGV[0] eq "-d") {
# have the servers display protocol output
$debugprotocol=1;
}
elsif ($ARGV[0] eq "-g") {
# run this test with gdb
$gdbthis=1;
}
elsif($ARGV[0] eq "-s") {
# short output
$short=1;
@@ -564,6 +590,8 @@ do {
print <<EOHELP
Usage: runtests.pl [-h][-s][-v][numbers]
-a continue even if a test fails
-d display server debug info
-g run the test case with gdb
-h this help text
-s short output
-v verbose output