Compare commits
33 Commits
curl-7_7_a
...
curl-7_7-b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b4f70aa2c8 | ||
![]() |
f54a282ccc | ||
![]() |
2a11bdc216 | ||
![]() |
5cd4c3ed24 | ||
![]() |
147a673063 | ||
![]() |
9ce5827fc1 | ||
![]() |
97f1c93674 | ||
![]() |
e61ceaf1bd | ||
![]() |
1118612249 | ||
![]() |
a23db7b7c7 | ||
![]() |
f6b6dff46a | ||
![]() |
55b8ceac18 | ||
![]() |
bcf448ee32 | ||
![]() |
91e4da7ddb | ||
![]() |
2873c18132 | ||
![]() |
5dd0a8a63e | ||
![]() |
2103dc41f5 | ||
![]() |
2ef13230cb | ||
![]() |
9479ac6dda | ||
![]() |
4e878eae79 | ||
![]() |
1e8e90a220 | ||
![]() |
fe95c7dc34 | ||
![]() |
6dae34d5da | ||
![]() |
36c621c9df | ||
![]() |
1717963e3d | ||
![]() |
4646a1ffa9 | ||
![]() |
0cb4eba002 | ||
![]() |
5eba359b5d | ||
![]() |
07ce7539a8 | ||
![]() |
c21f848c1c | ||
![]() |
84e94fda8b | ||
![]() |
ebd6897b10 | ||
![]() |
5ab8a9d32f |
21
CHANGES
21
CHANGES
@@ -6,7 +6,26 @@
|
|||||||
|
|
||||||
History of Changes
|
History of Changes
|
||||||
|
|
||||||
** curl 7.7 DOES NOT currently WORK. **
|
|
||||||
|
Daniel (8 March 2001)
|
||||||
|
- "Transfer-Encoding: chunked" is no longer any trouble for libcurl. I've
|
||||||
|
added two source files and I've run some test downloads that look fine.
|
||||||
|
|
||||||
|
Daniel (5 March 2001)
|
||||||
|
- The current 57 test cases now pass OK. It would suggest that libcurl works
|
||||||
|
using the old-style with one connection per handle. The test suite doesn't
|
||||||
|
handle multiple connections yet so there are no test cases for this.
|
||||||
|
|
||||||
|
- I patched the telnet.c heavily to not use any global variables anymore. It
|
||||||
|
should make it a lot nicer library-wise.
|
||||||
|
|
||||||
|
- The file:// support was modified slightly to use the internal connect-first-
|
||||||
|
then-do approach.
|
||||||
|
|
||||||
|
Daniel (4 March 2001)
|
||||||
|
- More bugs erased.
|
||||||
|
|
||||||
|
Version 7.7-alpha2
|
||||||
|
|
||||||
Daniel (4 March 2001)
|
Daniel (4 March 2001)
|
||||||
- Now, there's even a basic check that a re-used connection is still alive
|
- Now, there's even a basic check that a re-used connection is still alive
|
||||||
|
@@ -43,3 +43,8 @@
|
|||||||
/* Define this to 'int' if ssize_t is not an available typedefed type */
|
/* Define this to 'int' if ssize_t is not an available typedefed type */
|
||||||
#undef ssize_t
|
#undef ssize_t
|
||||||
|
|
||||||
|
/* Define this as a suitable file to read random data from */
|
||||||
|
#undef RANDOM_FILE
|
||||||
|
|
||||||
|
/* Define this to your Entropy Gathering Daemon socket pathname */
|
||||||
|
#undef EGD_SOCKET
|
||||||
|
33
configure.in
33
configure.in
@@ -391,6 +391,36 @@ AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(ucb, gethostname))
|
|||||||
dnl dl lib?
|
dnl dl lib?
|
||||||
AC_CHECK_FUNC(dlopen, , AC_CHECK_LIB(dl, dlopen))
|
AC_CHECK_FUNC(dlopen, , AC_CHECK_LIB(dl, dlopen))
|
||||||
|
|
||||||
|
dnl **********************************************************************
|
||||||
|
dnl Check for the random seed preferences
|
||||||
|
dnl **********************************************************************
|
||||||
|
|
||||||
|
AC_ARG_WITH(egd-socket,
|
||||||
|
[ --with-egd-socket=FILE Entropy Gathering Daemon socket pathname],
|
||||||
|
[ EGD_SOCKET="$withval" ]
|
||||||
|
)
|
||||||
|
if test -n "$EGD_SOCKET" ; then
|
||||||
|
AC_DEFINE_UNQUOTED(EGD_SOCKET, "$EGD_SOCKET")
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Check for user-specified random device
|
||||||
|
AC_ARG_WITH(random,
|
||||||
|
[ --with-random=FILE read randomness from FILE (default=/dev/urandom)],
|
||||||
|
[ RANDOM_FILE="$withval" ],
|
||||||
|
[
|
||||||
|
dnl Check for random device
|
||||||
|
AC_CHECK_FILE("/dev/urandom",
|
||||||
|
[
|
||||||
|
RANDOM_FILE="/dev/urandom";
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if test -n "$RANDOM_FILE" ; then
|
||||||
|
AC_SUBST(RANDOM_FILE)
|
||||||
|
AC_DEFINE_UNQUOTED(RANDOM_FILE, "$RANDOM_FILE")
|
||||||
|
fi
|
||||||
|
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
dnl Check for the presence of Kerberos4 libraries and headers
|
dnl Check for the presence of Kerberos4 libraries and headers
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
@@ -545,7 +575,8 @@ else
|
|||||||
dnl these can only exist if openssl exists
|
dnl these can only exist if openssl exists
|
||||||
|
|
||||||
AC_CHECK_FUNCS( RAND_status \
|
AC_CHECK_FUNCS( RAND_status \
|
||||||
RAND_screen )
|
RAND_screen \
|
||||||
|
RAND_egd )
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
12
docs/FAQ
12
docs/FAQ
@@ -1,4 +1,4 @@
|
|||||||
Updated: February 16, 2001 (http://curl.haxx.se/docs/faq.shtml)
|
Updated: March 6, 2001 (http://curl.haxx.se/docs/faq.shtml)
|
||||||
_ _ ____ _
|
_ _ ____ _
|
||||||
___| | | | _ \| |
|
___| | | | _ \| |
|
||||||
/ __| | | | |_) | |
|
/ __| | | | |_) | |
|
||||||
@@ -31,7 +31,7 @@ FAQ
|
|||||||
3.7 Can I use curl to delete/rename a file through FTP?
|
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.8 How do I tell curl to follow HTTP redirects?
|
||||||
3.9 How do I use curl in PHP?
|
3.9 How do I use curl in PHP?
|
||||||
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
|
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
||||||
|
|
||||||
4. Running Problems
|
4. Running Problems
|
||||||
4.1 Problems connecting to SSL servers.
|
4.1 Problems connecting to SSL servers.
|
||||||
@@ -292,7 +292,7 @@ FAQ
|
|||||||
invoke the curl tool using a command line. This is the way to use curl if
|
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.
|
you're using PHP3 or PHP4 built without curl module support.
|
||||||
|
|
||||||
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
|
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*
|
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
|
protocol that is built ontop of HTTP. Protocols such as SOAP, WEBDAV and
|
||||||
@@ -486,6 +486,9 @@ FAQ
|
|||||||
|
|
||||||
5.3 How do I fetch multiple files with libcurl?
|
5.3 How do I fetch multiple files with libcurl?
|
||||||
|
|
||||||
|
Starting with version 7.7, curl and libcurl will have excellent support for
|
||||||
|
transferring multiple files.
|
||||||
|
|
||||||
The easy interface of libcurl does not support multiple requests using the
|
The easy interface of libcurl does not support multiple requests using the
|
||||||
same connection. The only available way to do multiple requests is to
|
same connection. The only available way to do multiple requests is to
|
||||||
init/perform/cleanup for each request.
|
init/perform/cleanup for each request.
|
||||||
@@ -512,6 +515,9 @@ FAQ
|
|||||||
|
|
||||||
5.6 What about Keep-Alive or persistant connections?
|
5.6 What about Keep-Alive or persistant connections?
|
||||||
|
|
||||||
|
Starting with version 7.7, curl and libcurl will have excellent support for
|
||||||
|
persistant connections when transferring several files from the same server.
|
||||||
|
|
||||||
This is closely related to issue 5.3. Since libcurl has no real support
|
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
|
for doing multiple file transfers, there's no support for Keep-Alive or
|
||||||
persistant connections either.
|
persistant connections either.
|
||||||
|
98
docs/LIBCURL
98
docs/LIBCURL
@@ -4,58 +4,84 @@
|
|||||||
| | | |_) | (__| |_| | | | |
|
| | | |_) | (__| |_| | | | |
|
||||||
|_|_|_.__/ \___|\__,_|_| |_|
|
|_|_|_.__/ \___|\__,_|_| |_|
|
||||||
|
|
||||||
|
How To Use Libcurl In Your C/C++ Program
|
||||||
|
|
||||||
How To Use Libcurl In Your Program
|
[ libcurl can be used directly from within your PHP or Perl programs as well,
|
||||||
|
look elsewhere for documentation on this ]
|
||||||
|
|
||||||
Interfaces
|
The interface is meant to be very simple for applictions/programmers, hence
|
||||||
|
the name "easy". We have therefore minimized the number of entries.
|
||||||
libcurl currently offers two different interfaces to the URL transfer
|
|
||||||
engine. They can be seen as one low-level and one high-level, in the sense
|
|
||||||
that the low-level one will allow you to deal with a lot more details but on
|
|
||||||
the other hand not offer as many fancy features (such as Location:
|
|
||||||
following). The high-level interface is supposed to be a built-in
|
|
||||||
implementation of the low-level interface. You will not be able to mix
|
|
||||||
function calls from the different layers.
|
|
||||||
|
|
||||||
As we currently ONLY support the high-level interface, the so called easy
|
|
||||||
interface, I will not attempt to describe any low-level functions at this
|
|
||||||
point.
|
|
||||||
|
|
||||||
Function descriptions
|
|
||||||
|
|
||||||
The interface is meant to be very simple for very simple
|
|
||||||
implementations. Thus, we have minimized the number of entries.
|
|
||||||
|
|
||||||
The Easy Interface
|
The Easy Interface
|
||||||
|
|
||||||
When using the easy interface, you init your easy-session and get a handle,
|
When using the easy interface, you init your session and get a handle, which
|
||||||
which you use as input to the following interface functions you use.
|
you use as input to the following interface functions you use. Use
|
||||||
|
curl_easy_init() to get the handle.
|
||||||
|
|
||||||
You continue by setting all the options you want in the upcoming transfer,
|
You continue by setting all the options you want in the upcoming transfer,
|
||||||
most important among them is the URL itself. You might want to set some
|
most important among them is the URL itself (you can't transfer anything
|
||||||
callbacks as well that will be called from the library when data is available
|
without a specified URL as you may have figured out yourself). You might want
|
||||||
etc.
|
to set some callbacks as well that will be called from the library when data
|
||||||
|
is available etc. curl_easy_setopt() is there for this.
|
||||||
|
|
||||||
When all is setup, you tell libcurl to perform the transfer. It will then do
|
When all is setup, you tell libcurl to perform the transfer using
|
||||||
the entire operation and won't return until it is done or failed.
|
curl_easy_perform(). It will then do the entire operation and won't return
|
||||||
|
until it is done or failed.
|
||||||
|
|
||||||
After the transfer has been made, you cleanup the easy-session's handle and
|
After the transfer has been made, you cleanup the session with
|
||||||
libcurl is entirely off the hook!
|
curl_easy_cleanup() and libcurl is entirely off the hook! If you want
|
||||||
|
persistant connections, you don't cleanup immediately, but instead run ahead
|
||||||
|
and perform other transfers. See the chapter below for Persistant
|
||||||
|
Connections.
|
||||||
|
|
||||||
curl_easy_init()
|
While the above mentioned four functions are the main functions to use in the
|
||||||
curl_easy_setopt()
|
easy interface, there is a series of other helpful functions to use. They
|
||||||
curl_easy_perform()
|
are:
|
||||||
curl_easy_cleanup()
|
|
||||||
|
|
||||||
While the above four functions are the main functions to use in the easy
|
|
||||||
interface, there is a series of helpful functions to use. They are:
|
|
||||||
|
|
||||||
curl_version() - displays the libcurl version
|
curl_version() - displays the libcurl version
|
||||||
curl_getdate() - converts a date string to time_t
|
curl_getdate() - converts a date string to time_t
|
||||||
curl_getenv() - portable environment variable reader
|
curl_getenv() - portable environment variable reader
|
||||||
|
curl_easy_getinfo() - get information about a performed transfer
|
||||||
curl_formparse() - helps building a HTTP form POST
|
curl_formparse() - helps building a HTTP form POST
|
||||||
|
curl_formfree() - free a list built with curl_formparse()
|
||||||
curl_slist_append() - builds a linked list
|
curl_slist_append() - builds a linked list
|
||||||
curl_slist_free_all() - frees a whole curl_slist
|
curl_slist_free_all() - frees a whole curl_slist
|
||||||
|
|
||||||
Read the separate man pages for these functions for details!
|
For details on these, read the separate man pages.
|
||||||
|
|
||||||
|
Portability
|
||||||
|
|
||||||
|
libcurl works *exactly* the same, on any of the platforms it compiles and
|
||||||
|
builds on.
|
||||||
|
|
||||||
|
There's only one caution, and that is the win32 platform that may(*) require
|
||||||
|
you to init the winsock stuff before you use the libcurl functions. Details
|
||||||
|
on this are noted on the curl_easy_init() man page.
|
||||||
|
|
||||||
|
(*) = it appears users of the cygwin environment gets this done
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
Persistant Connections
|
||||||
|
|
||||||
|
With libcurl 7.7, persistant connections were added. Persistant connections
|
||||||
|
means that libcurl can re-use the same connection for several transfers, if
|
||||||
|
the conditions are right.
|
||||||
|
|
||||||
|
libcurl will *always* attempt to use persistant connections. Whenever you use
|
||||||
|
curl_easy_perform(), libcurl will attempt to use an existing connection to do
|
||||||
|
the transfer, and if none exists it'll open a new one that will be subject
|
||||||
|
for re-use on a possible following call to curl_easy_perform().
|
||||||
|
|
||||||
|
To allow libcurl to take full advantage of persistant connections, you should
|
||||||
|
do as many of your file transfers as possible using the same curl
|
||||||
|
handle. When you call curl_easy_cleanup(), all the possibly open connections
|
||||||
|
held by libcurl will be closed and forgotten.
|
||||||
|
|
||||||
|
Note that the options set with curl_easy_setopt() will be used in on every
|
||||||
|
repeat curl_easy_perform() call
|
||||||
|
|
||||||
|
Compatibility with older libcurls
|
||||||
|
|
||||||
|
Repeated curl_easy_perform() calls on the same handle were not supported in
|
||||||
|
pre-7.7 versions, and caused confusion and defined behaviour.
|
||||||
|
|
||||||
|
69
docs/TODO
69
docs/TODO
@@ -6,22 +6,28 @@
|
|||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
For the future
|
Things to do in project cURL. Please tell me what you think, contribute and
|
||||||
|
send me patches that improve things!
|
||||||
|
|
||||||
Ok, this is what I wanna do with Curl. Please tell me what you think, and
|
To do for the 7.7 release:
|
||||||
please don't hesitate to contribute and send me patches that improve this
|
|
||||||
product! (Yes, you may add things not mentioned here, these are just a
|
* Fix the random seeding. Add --egd-socket and --random-file options to the
|
||||||
few teasers...)
|
curl client and libcurl curl_easy_setopt() interface.
|
||||||
|
|
||||||
|
* Support persistant connections (fully detailed elsewhere)
|
||||||
|
|
||||||
|
* Add a special connection-timeout that only goes for the connection phase.
|
||||||
|
|
||||||
|
To do for the 7.8 release:
|
||||||
|
|
||||||
* Make SSL session ids get used if multiple HTTPS documents from the same
|
* Make SSL session ids get used if multiple HTTPS documents from the same
|
||||||
host is requested.
|
host is requested.
|
||||||
|
|
||||||
* Make the curl tool support URLs that start with @ that would then mean that
|
To do in a future release:
|
||||||
the following is a plain list with URLs to download. Thus @filename.txt
|
|
||||||
reads a list of URLs from a local file. A fancy option would then be to
|
* Extend the test suite to include telnet and https. The telnet could just do
|
||||||
support @http://whatever.com that would first load a list and then get the
|
ftp or http operations (for which we have test servers) and the https would
|
||||||
URLs mentioned in the list. I figure -O or something would have to be
|
probably work against/with some of the openssl tools.
|
||||||
implied by such an action.
|
|
||||||
|
|
||||||
* Add a command line option that allows the output file to get the same time
|
* Add a command line option that allows the output file to get the same time
|
||||||
stamp as the remote file. libcurl already is capable of fetching the remote
|
stamp as the remote file. libcurl already is capable of fetching the remote
|
||||||
@@ -31,16 +37,11 @@ For the future
|
|||||||
an alternative to OpenSSL:
|
an alternative to OpenSSL:
|
||||||
http://www.mozilla.org/projects/security/pki/nss/
|
http://www.mozilla.org/projects/security/pki/nss/
|
||||||
|
|
||||||
* Make sure the low-level interface works. highlevel.c should basically be
|
|
||||||
possible to write using that interface. Document the low-level interface
|
|
||||||
|
|
||||||
* Make the easy-interface support multiple file transfers. If they're done
|
|
||||||
to the same host, they should use persistant connections or similar.
|
|
||||||
Figure out a nice design for this.
|
|
||||||
|
|
||||||
* Add asynchronous name resolving, as this enables full timeout support for
|
* Add asynchronous name resolving, as this enables full timeout support for
|
||||||
fork() systems.
|
fork() systems.
|
||||||
|
|
||||||
|
* Non-blocking connect(), also to make timeouts work on windows.
|
||||||
|
|
||||||
* Move non-URL related functions that are used by both the lib and the curl
|
* Move non-URL related functions that are used by both the lib and the curl
|
||||||
application to a separate "portability lib".
|
application to a separate "portability lib".
|
||||||
|
|
||||||
@@ -48,14 +49,13 @@ For the future
|
|||||||
something being worked on in this area) and perl (we have seen the first
|
something being worked on in this area) and perl (we have seen the first
|
||||||
versions of this!) comes to mind. Python anyone?
|
versions of this!) comes to mind. Python anyone?
|
||||||
|
|
||||||
* "Content-Encoding: compress/gzip/zlib"
|
* "Content-Encoding: compress/gzip/zlib" HTTP 1.1 clearly defines how to get
|
||||||
|
and decode compressed documents. There is the zlib that is pretty good at
|
||||||
|
decompressing stuff. This work was started in October 1999 but halted again
|
||||||
|
since it proved more work than we thought. It is still a good idea to
|
||||||
|
implement though.
|
||||||
|
|
||||||
HTTP 1.1 clearly defines how to get and decode compressed documents. There
|
* Authentication: NTLM. Support for that MS crap called NTLM
|
||||||
is the zlib that is pretty good at decompressing stuff. This work was
|
|
||||||
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 to support that MS crap called NTLM
|
|
||||||
authentication. MS proxies and servers sometime require that. Since that
|
authentication. MS proxies and servers sometime require that. Since that
|
||||||
protocol is a proprietary one, it involves reverse engineering and network
|
protocol is a proprietary one, it involves reverse engineering and network
|
||||||
sniffing. This should however be a library-based functionality. There are a
|
sniffing. This should however be a library-based functionality. There are a
|
||||||
@@ -70,30 +70,19 @@ For the future
|
|||||||
http://hopf.math.nwu.edu/testpage/digest/
|
http://hopf.math.nwu.edu/testpage/digest/
|
||||||
And some friendly person's server source code is available at
|
And some friendly person's server source code is available at
|
||||||
http://hopf.math.nwu.edu/digestauth/index.html
|
http://hopf.math.nwu.edu/digestauth/index.html
|
||||||
|
|
||||||
Then there's the Apache mod_digest source code too of course. It seems as
|
Then there's the Apache mod_digest source code too of course. It seems as
|
||||||
if Netscape doesn't support this, and not many servers do. Although this is
|
if Netscape doesn't support this, and not many servers do. Although this is
|
||||||
a lot better authentication method than the more common "Basic". Basic
|
a lot better authentication method than the more common "Basic". Basic
|
||||||
sends the password in cleartext over the network, this "Digest" method uses
|
sends the password in cleartext over the network, this "Digest" method uses
|
||||||
a challange-response protocol which increases security quite a lot.
|
a challange-response protocol which increases security quite a lot.
|
||||||
|
|
||||||
* Multiple Proxies?
|
|
||||||
Is there anyone that actually uses serial-proxies? I mean, send CONNECT to
|
|
||||||
the first proxy to connect to the second proxy to which you send CONNECT to
|
|
||||||
connect to the remote host (or even more iterations). Is there anyone
|
|
||||||
wanting curl to support it? (Not that it would be hard, just confusing...)
|
|
||||||
|
|
||||||
* Other proxies
|
* Other proxies
|
||||||
Ftp-kind proxy, Socks5, whatever kind of proxies are there?
|
Ftp-kind proxy, Socks5, whatever kind of proxies are there?
|
||||||
|
|
||||||
* IPv6 Awareness and support
|
* IPv6 Awareness and support. (This is partly done.) RFC 2428 "FTP
|
||||||
Where ever it would fit. configure search for v6-versions of a few
|
Extensions for IPv6 and NATs" is interesting. PORT should be replaced with
|
||||||
functions and then use them instead is of course the first thing to do...
|
EPRT for IPv6 (done), and EPSV instead of PASV. HTTP proxies are left to
|
||||||
RFC 2428 "FTP Extensions for IPv6 and NATs" will be interesting. PORT
|
add support for.
|
||||||
should be replaced with EPRT for IPv6, and EPSV instead of PASV.
|
|
||||||
|
|
||||||
* SSL for more protocols, like SSL-FTP...
|
* SSL for more protocols, like SSL-FTP...
|
||||||
(http://search.ietf.org/internet-drafts/draft-murray-auth-ftp-ssl-05.txt)
|
(http://search.ietf.org/internet-drafts/draft-murray-auth-ftp-ssl-05.txt)
|
||||||
|
|
||||||
* HTTP POST resume using Range:
|
|
||||||
|
|
||||||
|
@@ -2,13 +2,13 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_cleanup 3 "22 May 2000" "Curl 7.0" "libcurl Manual"
|
.TH curl_easy_cleanup 3 "5 March 2001" "libcurl 7.7" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_cleanup - End a libcurl "easy" session
|
curl_easy_cleanup - End a libcurl session
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/easy.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "curl_easy_cleanup(CURL *" handle ");
|
.BI "curl_easy_cleanup(CURL *" handle ");"
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This function must be the last function to call for a curl session. It is the
|
This function must be the last function to call for a curl session. It is the
|
||||||
@@ -17,6 +17,10 @@ opposite of the
|
|||||||
function and must be called with the same
|
function and must be called with the same
|
||||||
.I handle
|
.I handle
|
||||||
as input as the curl_easy_init call returned.
|
as input as the curl_easy_init call returned.
|
||||||
|
|
||||||
|
This will effectively close all connections libcurl has been used and possibly
|
||||||
|
has kept open until now. Don't call this function if you intend to transfer
|
||||||
|
more files (libcurl 7.7 or later).
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
None
|
None
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_init 3 "4 February 2001" "Curl 7.6.1" "libcurl Manual"
|
.TH curl_easy_init 3 "5 March 2001" "libcurl 7.6.1" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
|
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/easy.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"
|
.BI "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"
|
||||||
.ad
|
.ad
|
||||||
@@ -83,8 +83,8 @@ verification that was requested (using the CURLOPT_SSL_VERIFYPEER option to
|
|||||||
curl_easy_setopt). (Added in 7.4.2)
|
curl_easy_setopt). (Added in 7.4.2)
|
||||||
.TP
|
.TP
|
||||||
.B CURLINFO_CONTENT_LENGTH_DOWNLOAD
|
.B CURLINFO_CONTENT_LENGTH_DOWNLOAD
|
||||||
Pass a pointer to a double to receive the content-length of the download.
|
Pass a pointer to a double to receive the content-length of the download. This
|
||||||
(Added in 7.6.1)
|
is the value read from the Content-Length: field. (Added in 7.6.1)
|
||||||
.TP
|
.TP
|
||||||
.B CURLINFO_CONTENT_LENGTH_UPLOAD
|
.B CURLINFO_CONTENT_LENGTH_UPLOAD
|
||||||
Pass a pointer to a double to receive the specified size of the upload.
|
Pass a pointer to a double to receive the specified size of the upload.
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_init 3 "26 September 2000" "Curl 7.0" "libcurl Manual"
|
.TH curl_easy_init 3 "5 March 2001" "libcurl 7.7" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_init - Start a libcurl "easy" session
|
curl_easy_init - Start a libcurl session
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/easy.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "CURL *curl_easy_init( );"
|
.BI "CURL *curl_easy_init( );"
|
||||||
.ad
|
.ad
|
||||||
@@ -19,6 +19,10 @@ when the operation is complete.
|
|||||||
|
|
||||||
On win32 systems, you need to init the winsock stuff manually, libcurl will
|
On win32 systems, you need to init the winsock stuff manually, libcurl will
|
||||||
not do that for you. WSAStartup() and WSACleanup() should be used accordingly.
|
not do that for you. WSAStartup() and WSACleanup() should be used accordingly.
|
||||||
|
|
||||||
|
Using libcurl 7.7 and later, you should perform all your sequential file
|
||||||
|
transfers using the same curl handle. This enables libcurl to use persistant
|
||||||
|
connections where possible.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
If this function returns NULL, something went wrong and you cannot use the
|
If this function returns NULL, something went wrong and you cannot use the
|
||||||
other curl functions.
|
other curl functions.
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_perform 3 "1 Mar 2001" "Curl 7.0" "libcurl Manual"
|
.TH curl_easy_perform 3 "5 Mar 2001" "libcurl 7.7" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_perform - Do the actual transfer in a "easy" session
|
curl_easy_perform - Perform a file transfer
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/easy.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "CURLcode curl_easy_perform(CURL *" handle ");
|
.BI "CURLcode curl_easy_perform(CURL *" handle ");
|
||||||
.ad
|
.ad
|
||||||
@@ -17,9 +17,22 @@ It must be called with the same
|
|||||||
.I handle
|
.I handle
|
||||||
as input as the curl_easy_init call returned.
|
as input as the curl_easy_init call returned.
|
||||||
|
|
||||||
You are only allowed to call this function once using the same handle. If you
|
libcurl version 7.7 or later (for older versions see below): You can do any
|
||||||
want to do repeated calls, you must call curl_easy_cleanup and curl_easy_init
|
amount of calls to curl_easy_perform() while using the same handle. If you
|
||||||
again first.
|
intend to transfer more than one file, you are even encouraged to do
|
||||||
|
so. libcurl will then attempt to re-use the same connection for the following
|
||||||
|
transfers, thus making the operations faster, less CPU intense and using less
|
||||||
|
network resources. Just note that you will have to use
|
||||||
|
.I curl_easy_setopt
|
||||||
|
between the invokes to set options for the following curl_easy_perform.
|
||||||
|
|
||||||
|
You must never call this function simultaneously from two places using the
|
||||||
|
same handle. Let the function return first before invoking it another time. If
|
||||||
|
you want parallel transfers, you must use several curl handles.
|
||||||
|
|
||||||
|
Before libcurl version 7.7: You are only allowed to call this function once
|
||||||
|
using the same handle. If you want to do repeated calls, you must call
|
||||||
|
curl_easy_cleanup and curl_easy_init again first.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
0 means everything was ok, non-zero means an error occurred as
|
0 means everything was ok, non-zero means an error occurred as
|
||||||
.I <curl/curl.h>
|
.I <curl/curl.h>
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_setopt 3 "2 February 2001" "Curl 7.5" "libcurl Manual"
|
.TH curl_easy_setopt 3 "6 March 2001" "libcurl 7.5" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_setopt - Set curl easy-session options
|
curl_easy_setopt - Set curl easy-session options
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/easy.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);
|
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);
|
||||||
.ad
|
.ad
|
||||||
@@ -20,7 +20,11 @@ followed by a parameter. That parameter can be a long, a function pointer or
|
|||||||
an object pointer, all depending on what the option in question expects. Read
|
an object pointer, all depending on what the option in question expects. Read
|
||||||
this manual carefully as bad input values may cause libcurl to behave badly!
|
this manual carefully as bad input values may cause libcurl to behave badly!
|
||||||
You can only set one option in each function call. A typical application uses
|
You can only set one option in each function call. A typical application uses
|
||||||
many calls in the setup phase.
|
many curl_easy_setopt() calls in the setup phase.
|
||||||
|
|
||||||
|
NOTE: strings passed to libcurl as 'char *' arguments, will not be copied by
|
||||||
|
the library. Instead you should keep them available until libcurl no longer
|
||||||
|
needs them. Failing to do so will cause very odd behaviour or even crashes.
|
||||||
|
|
||||||
The
|
The
|
||||||
.I "handle"
|
.I "handle"
|
||||||
@@ -86,14 +90,16 @@ libcurl what the expected size of the infile is.
|
|||||||
.TP
|
.TP
|
||||||
.B CURLOPT_URL
|
.B CURLOPT_URL
|
||||||
The actual URL to deal with. The parameter should be a char * to a zero
|
The actual URL to deal with. The parameter should be a char * to a zero
|
||||||
terminated string. NOTE: this option is currently required!
|
terminated string. The string must remain present until curl no longer needs
|
||||||
|
it, as it doesn't copy the string. NOTE: this option is required to be set
|
||||||
|
before curl_easy_perform() is called.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PROXY
|
.B CURLOPT_PROXY
|
||||||
If you need libcurl to use a http proxy to access the outside world, set the
|
If you need libcurl to use a http proxy to access the outside world, set the
|
||||||
proxy string with this option. The parameter should be a char * to a zero
|
proxy string with this option. The parameter should be a char * to a zero
|
||||||
terminated string. To specify port number in this string, append":[port]" to
|
terminated string. To specify port number in this string, append :[port] to
|
||||||
the end of the host name. The proxy string may be prefixed with
|
the end of the host name. The proxy string may be prefixed with
|
||||||
"[protocol]://" since any such prefix will be ignored.
|
[protocol]:// since any such prefix will be ignored.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_PROXYPORT
|
.B CURLOPT_PROXYPORT
|
||||||
Set this long with this option to set the proxy port to use unless it is
|
Set this long with this option to set the proxy port to use unless it is
|
||||||
@@ -189,9 +195,11 @@ prompted for it.
|
|||||||
.TP
|
.TP
|
||||||
.B CURLOPT_RANGE
|
.B CURLOPT_RANGE
|
||||||
Pass a char * as parameter, which should contain the specified range you
|
Pass a char * as parameter, which should contain the specified range you
|
||||||
want. It should be in the format "X-Y", where X or Y may be left out. The HTTP
|
want. It should be in the format "X-Y", where X or Y may be left out. HTTP
|
||||||
transfers also support several intervals, separated with commas as in
|
transfers also support several intervals, separated with commas as in
|
||||||
.I "X-Y,N-M".
|
.I "X-Y,N-M"
|
||||||
|
. Using this kind of multiple intervals will cause the HTTP server to send the
|
||||||
|
response document in pieces.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_ERRORBUFFER
|
.B CURLOPT_ERRORBUFFER
|
||||||
Pass a char * to a buffer that the libcurl may store human readable error
|
Pass a char * to a buffer that the libcurl may store human readable error
|
||||||
@@ -202,7 +210,8 @@ library. The buffer must be at least CURL_ERROR_SIZE big.
|
|||||||
Pass a long as parameter containing the maximum time in seconds that you allow
|
Pass a long as parameter containing the maximum time in seconds that you allow
|
||||||
the libcurl transfer operation to take. Do note that normally, name lookups
|
the libcurl transfer operation to take. Do note that normally, name lookups
|
||||||
maky take a considerable time and that limiting the operation to less than a
|
maky take a considerable time and that limiting the operation to less than a
|
||||||
few minutes risk aborting perfectly normal operations.
|
few minutes risk aborting perfectly normal operations. This option will cause
|
||||||
|
curl to use the SIGALRM to enable timeouting system calls.
|
||||||
.TP
|
.TP
|
||||||
.B CURLOPT_POSTFIELDS
|
.B CURLOPT_POSTFIELDS
|
||||||
Pass a char * as parameter, which should be the full data to post in a HTTP
|
Pass a char * as parameter, which should be the full data to post in a HTTP
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_formfree 3 "17 November 2000" "Curl 7.5" "libcurl Manual"
|
.TH curl_formfree 3 "5 March 2001" "libcurl 7.5" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_formfree - free a previously build multipart/formdata HTTP POST chain
|
curl_formfree - free a previously build multipart/formdata HTTP POST chain
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_formparse 3 "22 February 2001" "Curl 7.0" "libcurl Manual"
|
.TH curl_formparse 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_formparse - add a section to a multipart/formdata HTTP POST
|
curl_formparse - add a section to a multipart/formdata HTTP POST
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_getdate 3 "2 June 2000" "Curl 7.0" "libcurl Manual"
|
.TH curl_getdate 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_getdate - Convert an date in a ASCII string to number of seconds since
|
curl_getdate - Convert an date in a ASCII string to number of seconds since
|
||||||
January 1, 1970
|
January 1, 1970
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_getenv 3 "2 June 2000" "Curl 7.0" "libcurl Manual"
|
.TH curl_getenv 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_getenv - return value for environment name
|
curl_getenv - return value for environment name
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_slist_append 3 "1 Mar 2001" "Curl 7.7" "libcurl Manual"
|
.TH curl_slist_append 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_slist_append - add a string to an slist
|
curl_slist_append - add a string to an slist
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@@ -2,13 +2,13 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_slist_free_all 3 "2 June 2000" "Curl 7.0" "libcurl Manual"
|
.TH curl_slist_free_all 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_slist_free_all - free an entire curl_slist list
|
curl_slist_free_all - free an entire curl_slist list
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/curl.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "void curl_slist_free_all(struct curl_slit *" list);
|
.BI "void curl_slist_free_all(struct curl_slist *" list);
|
||||||
.ad
|
.ad
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
curl_slist_free_all() removes all traces of a previously built curl_slist
|
curl_slist_free_all() removes all traces of a previously built curl_slist
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" Written by daniel@haxx.se
|
.\" Written by daniel@haxx.se
|
||||||
.\"
|
.\"
|
||||||
.TH curl_version 3 "2 June 2000" "Curl 7.0" "libcurl Manual"
|
.TH curl_version 3 "5 March 2001" "libcurl 7.0" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_version - returns the libcurl version string
|
curl_version - returns the libcurl version string
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B #include <curl/easy.h>
|
.B #include <curl/curl.h>
|
||||||
.sp
|
.sp
|
||||||
.BI "char *curl_version( );"
|
.BI "char *curl_version( );"
|
||||||
.ad
|
.ad
|
||||||
@@ -14,9 +14,9 @@ curl_version - returns the libcurl version string
|
|||||||
Returns a human readable string with the version number of libcurl and some of
|
Returns a human readable string with the version number of libcurl and some of
|
||||||
its important components (like OpenSSL version).
|
its important components (like OpenSSL version).
|
||||||
|
|
||||||
Do note that this returns the actual running lib's version, you might have
|
Note: this returns the actual running lib's version, you might have installed
|
||||||
installed a newer lib's include files in your system which may turn your
|
a newer lib's include files in your system which may turn your LIBCURL_VERSION
|
||||||
LIBCURL_VERSION #define value to differ from this result.
|
#define value to differ from this result.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
A pointer to a zero terminated string.
|
A pointer to a zero terminated string.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
|||||||
|
|
||||||
EXTRA_DIST =
|
EXTRA_DIST =
|
||||||
README curlgtk.c sepheaders.c simple.c postit.c \
|
README curlgtk.c sepheaders.c simple.c postit.c \
|
||||||
win32sockets.c \
|
win32sockets.c persistant.c \
|
||||||
getpageinvar.php simpleget.php simplepost.php
|
getpageinvar.php simpleget.php simplepost.php
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
53
docs/examples/persistant.c
Normal file
53
docs/examples/persistant.c
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
/* to make this work under windows, use the win32-functions from the
|
||||||
|
docs/examples/win32socket.c file as well */
|
||||||
|
|
||||||
|
/* This example REQUIRES libcurl 7.7 or later */
|
||||||
|
#if (LIBCURL_VERSION_NUM < 0x070700)
|
||||||
|
#error Too old libcurl version, upgrade or stay away.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
/* this sends all memory debug messages to a specified logfile */
|
||||||
|
curl_memdebug("memdump");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
|
||||||
|
|
||||||
|
/* get the first document */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/");
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* get another document from the same server using the same
|
||||||
|
connection */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/docs/");
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
/* always cleanup */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -97,71 +97,57 @@ typedef int (*curl_passwd_callback)(void *clientp,
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CURLE_OK = 0,
|
CURLE_OK = 0,
|
||||||
CURLE_UNSUPPORTED_PROTOCOL,
|
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
|
||||||
CURLE_FAILED_INIT,
|
CURLE_FAILED_INIT, /* 2 */
|
||||||
CURLE_URL_MALFORMAT,
|
CURLE_URL_MALFORMAT, /* 3 */
|
||||||
CURLE_URL_MALFORMAT_USER,
|
CURLE_URL_MALFORMAT_USER, /* 4 */
|
||||||
CURLE_COULDNT_RESOLVE_PROXY,
|
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
|
||||||
CURLE_COULDNT_RESOLVE_HOST,
|
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
|
||||||
CURLE_COULDNT_CONNECT,
|
CURLE_COULDNT_CONNECT, /* 7 */
|
||||||
CURLE_FTP_WEIRD_SERVER_REPLY,
|
CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
|
||||||
CURLE_FTP_ACCESS_DENIED,
|
CURLE_FTP_ACCESS_DENIED, /* 9 */
|
||||||
CURLE_FTP_USER_PASSWORD_INCORRECT,
|
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */
|
||||||
CURLE_FTP_WEIRD_PASS_REPLY,
|
CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
|
||||||
CURLE_FTP_WEIRD_USER_REPLY,
|
CURLE_FTP_WEIRD_USER_REPLY, /* 12 */
|
||||||
CURLE_FTP_WEIRD_PASV_REPLY,
|
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
|
||||||
CURLE_FTP_WEIRD_227_FORMAT,
|
CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
|
||||||
CURLE_FTP_CANT_GET_HOST,
|
CURLE_FTP_CANT_GET_HOST, /* 15 */
|
||||||
CURLE_FTP_CANT_RECONNECT,
|
CURLE_FTP_CANT_RECONNECT, /* 16 */
|
||||||
CURLE_FTP_COULDNT_SET_BINARY,
|
CURLE_FTP_COULDNT_SET_BINARY, /* 17 */
|
||||||
CURLE_PARTIAL_FILE,
|
CURLE_PARTIAL_FILE, /* 18 */
|
||||||
CURLE_FTP_COULDNT_RETR_FILE,
|
CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
|
||||||
CURLE_FTP_WRITE_ERROR,
|
CURLE_FTP_WRITE_ERROR, /* 20 */
|
||||||
CURLE_FTP_QUOTE_ERROR,
|
CURLE_FTP_QUOTE_ERROR, /* 21 */
|
||||||
CURLE_HTTP_NOT_FOUND,
|
CURLE_HTTP_NOT_FOUND, /* 22 */
|
||||||
CURLE_WRITE_ERROR,
|
CURLE_WRITE_ERROR, /* 23 */
|
||||||
|
CURLE_MALFORMAT_USER, /* 24 - user name is illegally specified */
|
||||||
|
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
|
||||||
|
CURLE_READ_ERROR, /* 26 - could open/read from file */
|
||||||
|
CURLE_OUT_OF_MEMORY, /* 27 */
|
||||||
|
CURLE_OPERATION_TIMEOUTED, /* 28 - the timeout time was reached */
|
||||||
|
CURLE_FTP_COULDNT_SET_ASCII, /* 29 - TYPE A failed */
|
||||||
|
CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
|
||||||
|
CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
|
||||||
|
CURLE_FTP_COULDNT_GET_SIZE, /* 32 - the SIZE command failed */
|
||||||
|
CURLE_HTTP_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
|
||||||
|
CURLE_HTTP_POST_ERROR, /* 34 */
|
||||||
|
CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
|
||||||
|
CURLE_FTP_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
|
||||||
|
CURLE_FILE_COULDNT_READ_FILE, /* 37 */
|
||||||
|
CURLE_LDAP_CANNOT_BIND, /* 38 */
|
||||||
|
CURLE_LDAP_SEARCH_FAILED, /* 39 */
|
||||||
|
CURLE_LIBRARY_NOT_FOUND, /* 40 */
|
||||||
|
CURLE_FUNCTION_NOT_FOUND, /* 41 */
|
||||||
|
CURLE_ABORTED_BY_CALLBACK, /* 42 */
|
||||||
|
CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
|
||||||
|
CURLE_BAD_CALLING_ORDER, /* 44 */
|
||||||
|
CURLE_HTTP_PORT_FAILED, /* 45 - HTTP Interface operation failed */
|
||||||
|
CURLE_BAD_PASSWORD_ENTERED, /* 46 - my_getpass() returns fail */
|
||||||
|
CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
|
||||||
|
CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */
|
||||||
|
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
|
||||||
|
|
||||||
CURLE_MALFORMAT_USER, /* the user name is illegally specified */
|
CURL_LAST /* never use! */
|
||||||
CURLE_FTP_COULDNT_STOR_FILE, /* failed FTP upload */
|
|
||||||
CURLE_READ_ERROR, /* could open/read from file */
|
|
||||||
|
|
||||||
CURLE_OUT_OF_MEMORY,
|
|
||||||
CURLE_OPERATION_TIMEOUTED, /* the timeout time was reached */
|
|
||||||
CURLE_FTP_COULDNT_SET_ASCII, /* TYPE A failed */
|
|
||||||
|
|
||||||
CURLE_FTP_PORT_FAILED, /* FTP PORT operation failed */
|
|
||||||
|
|
||||||
CURLE_FTP_COULDNT_USE_REST, /* the REST command failed */
|
|
||||||
CURLE_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */
|
|
||||||
|
|
||||||
CURLE_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */
|
|
||||||
|
|
||||||
CURLE_HTTP_POST_ERROR,
|
|
||||||
|
|
||||||
CURLE_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
|
|
||||||
|
|
||||||
CURLE_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
|
|
||||||
|
|
||||||
CURLE_FILE_COULDNT_READ_FILE,
|
|
||||||
|
|
||||||
CURLE_LDAP_CANNOT_BIND,
|
|
||||||
CURLE_LDAP_SEARCH_FAILED,
|
|
||||||
CURLE_LIBRARY_NOT_FOUND,
|
|
||||||
CURLE_FUNCTION_NOT_FOUND,
|
|
||||||
|
|
||||||
CURLE_ABORTED_BY_CALLBACK,
|
|
||||||
CURLE_BAD_FUNCTION_ARGUMENT,
|
|
||||||
CURLE_BAD_CALLING_ORDER,
|
|
||||||
|
|
||||||
CURLE_HTTP_PORT_FAILED, /* HTTP Interface operation failed */
|
|
||||||
|
|
||||||
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;
|
} CURLcode;
|
||||||
|
|
||||||
/* This is just to make older programs not break: */
|
/* This is just to make older programs not break: */
|
||||||
@@ -458,8 +444,8 @@ char *curl_getenv(char *variable);
|
|||||||
char *curl_version(void);
|
char *curl_version(void);
|
||||||
|
|
||||||
/* This is the version number */
|
/* This is the version number */
|
||||||
#define LIBCURL_VERSION "7.7-alpha2"
|
#define LIBCURL_VERSION "7.7-beta1"
|
||||||
#define LIBCURL_VERSION_NUM 0x070000
|
#define LIBCURL_VERSION_NUM 0x070700
|
||||||
|
|
||||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||||
struct curl_slist {
|
struct curl_slist {
|
||||||
|
@@ -58,7 +58,8 @@ getenv.c ldap.h ssluse.h \
|
|||||||
escape.c mprintf.c telnet.c \
|
escape.c mprintf.c telnet.c \
|
||||||
escape.h getpass.c netrc.c telnet.h \
|
escape.h getpass.c netrc.c telnet.h \
|
||||||
getinfo.c transfer.c strequal.c strequal.h easy.c \
|
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
|
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
|
||||||
|
http_chunks.c http_chunks.h
|
||||||
|
|
||||||
noinst_HEADERS = setup.h transfer.h
|
noinst_HEADERS = setup.h transfer.h
|
||||||
|
|
||||||
|
58
lib/file.c
58
lib/file.c
@@ -91,25 +91,19 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CURLcode file(struct connectdata *conn)
|
/* Emulate a connect-then-transfer protocol. We connect to the file here */
|
||||||
|
CURLcode Curl_file_connect(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
/* This implementation ignores the host name in conformance with
|
char *actual_path = curl_unescape(conn->path, 0);
|
||||||
RFC 1738. Only local files (reachable via the standard file system)
|
struct FILE *file;
|
||||||
are supported. This means that files on remotely mounted directories
|
|
||||||
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
|
|
||||||
*/
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
char *path = conn->path;
|
|
||||||
struct stat statbuf;
|
|
||||||
size_t expected_size=-1;
|
|
||||||
size_t nread;
|
|
||||||
struct UrlData *data = conn->data;
|
|
||||||
char *buf = data->buffer;
|
|
||||||
int bytecount = 0;
|
|
||||||
struct timeval start = Curl_tvnow();
|
|
||||||
struct timeval now = start;
|
|
||||||
int fd;
|
int fd;
|
||||||
char *actual_path = curl_unescape(path, 0);
|
|
||||||
|
file = (struct FILE *)malloc(sizeof(struct FILE));
|
||||||
|
if(!file)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
memset(file, 0, sizeof(struct FILE));
|
||||||
|
conn->proto.file = file;
|
||||||
|
|
||||||
#if defined(WIN32) || defined(__EMX__)
|
#if defined(WIN32) || defined(__EMX__)
|
||||||
int i;
|
int i;
|
||||||
@@ -126,9 +120,37 @@ CURLcode file(struct connectdata *conn)
|
|||||||
free(actual_path);
|
free(actual_path);
|
||||||
|
|
||||||
if(fd == -1) {
|
if(fd == -1) {
|
||||||
failf(data, "Couldn't open file %s", path);
|
failf(conn->data, "Couldn't open file %s", conn->path);
|
||||||
return CURLE_FILE_COULDNT_READ_FILE;
|
return CURLE_FILE_COULDNT_READ_FILE;
|
||||||
}
|
}
|
||||||
|
file->fd = fd;
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the do-phase, separated from the connect-phase above */
|
||||||
|
|
||||||
|
CURLcode Curl_file(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
/* This implementation ignores the host name in conformance with
|
||||||
|
RFC 1738. Only local files (reachable via the standard file system)
|
||||||
|
are supported. This means that files on remotely mounted directories
|
||||||
|
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
|
||||||
|
*/
|
||||||
|
CURLcode res = CURLE_OK;
|
||||||
|
struct stat statbuf;
|
||||||
|
size_t expected_size=-1;
|
||||||
|
size_t nread;
|
||||||
|
struct UrlData *data = conn->data;
|
||||||
|
char *buf = data->buffer;
|
||||||
|
int bytecount = 0;
|
||||||
|
struct timeval start = Curl_tvnow();
|
||||||
|
struct timeval now = start;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/* get the fd from the connection phase */
|
||||||
|
fd = conn->proto.file->fd;
|
||||||
|
|
||||||
if( -1 != fstat(fd, &statbuf)) {
|
if( -1 != fstat(fd, &statbuf)) {
|
||||||
/* we could stat it, then read out the size */
|
/* we could stat it, then read out the size */
|
||||||
expected_size = statbuf.st_size;
|
expected_size = statbuf.st_size;
|
||||||
|
@@ -23,6 +23,6 @@
|
|||||||
*
|
*
|
||||||
* $Id$
|
* $Id$
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
CURLcode file(struct connectdata *conn);
|
CURLcode Curl_file(struct connectdata *conn);
|
||||||
|
CURLcode Curl_file_connect(struct connectdata *conn);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -296,6 +296,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
|||||||
memset(ftp, 0, sizeof(struct FTP));
|
memset(ftp, 0, sizeof(struct FTP));
|
||||||
conn->proto.ftp = ftp;
|
conn->proto.ftp = ftp;
|
||||||
|
|
||||||
|
/* We always support persistant connections on ftp */
|
||||||
|
conn->bits.close = FALSE;
|
||||||
|
|
||||||
/* get some initial data into the ftp struct */
|
/* get some initial data into the ftp struct */
|
||||||
ftp->bytecountp = &conn->bytecount;
|
ftp->bytecountp = &conn->bytecount;
|
||||||
|
|
||||||
|
@@ -104,6 +104,7 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
/*
|
/*
|
||||||
* The add_buffer series of functions are used to build one large memory chunk
|
* The add_buffer series of functions are used to build one large memory chunk
|
||||||
* from repeated function invokes. Used so that the entire HTTP request can
|
* from repeated function invokes. Used so that the entire HTTP request can
|
||||||
@@ -205,7 +206,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* end of the add_buffer functions */
|
/* end of the add_buffer functions */
|
||||||
/*****************************************************************************/
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read everything until a newline.
|
* Read everything until a newline.
|
||||||
@@ -309,6 +310,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HTTP stuff to do at connect-time.
|
||||||
|
*/
|
||||||
CURLcode Curl_http_connect(struct connectdata *conn)
|
CURLcode Curl_http_connect(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
struct UrlData *data;
|
struct UrlData *data;
|
||||||
@@ -402,6 +406,9 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
else
|
else
|
||||||
http = conn->proto.http;
|
http = conn->proto.http;
|
||||||
|
|
||||||
|
/* We default to persistant connections */
|
||||||
|
conn->bits.close = FALSE;
|
||||||
|
|
||||||
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
|
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
|
||||||
data->bits.upload) {
|
data->bits.upload) {
|
||||||
data->bits.http_put=1;
|
data->bits.http_put=1;
|
||||||
|
@@ -35,4 +35,9 @@ CURLcode Curl_http_done(struct connectdata *conn);
|
|||||||
CURLcode Curl_http_connect(struct connectdata *conn);
|
CURLcode Curl_http_connect(struct connectdata *conn);
|
||||||
CURLcode Curl_http_close(struct connectdata *conn);
|
CURLcode Curl_http_close(struct connectdata *conn);
|
||||||
|
|
||||||
|
/* The following functions are defined in http_chunks.c */
|
||||||
|
void Curl_httpchunk_init(struct connectdata *conn);
|
||||||
|
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
|
||||||
|
ssize_t length, ssize_t *wrote);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
191
lib/http_chunks.c
Normal file
191
lib/http_chunks.c
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, 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 "setup.h"
|
||||||
|
|
||||||
|
/* -- WIN32 approved -- */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "urldata.h" /* it includes http_chunks.h */
|
||||||
|
#include "sendf.h" /* for the client write stuff */
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
#include "memdebug.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chunk format (simplified):
|
||||||
|
*
|
||||||
|
* <HEX SIZE>[ chunk extension ] CRLF
|
||||||
|
* <DATA>
|
||||||
|
*
|
||||||
|
* Highlights from RFC2616 section 3.6 say:
|
||||||
|
|
||||||
|
The chunked encoding modifies the body of a message in order to
|
||||||
|
transfer it as a series of chunks, each with its own size indicator,
|
||||||
|
followed by an OPTIONAL trailer containing entity-header fields. This
|
||||||
|
allows dynamically produced content to be transferred along with the
|
||||||
|
information necessary for the recipient to verify that it has
|
||||||
|
received the full message.
|
||||||
|
|
||||||
|
Chunked-Body = *chunk
|
||||||
|
last-chunk
|
||||||
|
trailer
|
||||||
|
CRLF
|
||||||
|
|
||||||
|
chunk = chunk-size [ chunk-extension ] CRLF
|
||||||
|
chunk-data CRLF
|
||||||
|
chunk-size = 1*HEX
|
||||||
|
last-chunk = 1*("0") [ chunk-extension ] CRLF
|
||||||
|
|
||||||
|
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
||||||
|
chunk-ext-name = token
|
||||||
|
chunk-ext-val = token | quoted-string
|
||||||
|
chunk-data = chunk-size(OCTET)
|
||||||
|
trailer = *(entity-header CRLF)
|
||||||
|
|
||||||
|
The chunk-size field is a string of hex digits indicating the size of
|
||||||
|
the chunk. The chunked encoding is ended by any chunk whose size is
|
||||||
|
zero, followed by the trailer, which is terminated by an empty line.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void Curl_httpchunk_init(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
struct Curl_chunker *chunk = &conn->proto.http->chunk;
|
||||||
|
chunk->hexindex=0; /* start at 0 */
|
||||||
|
chunk->dataleft=0; /* no data left yet! */
|
||||||
|
chunk->state = CHUNK_HEX; /* we get hex first! */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* chunk_read() returns a OK for normal operations, or a positive return code
|
||||||
|
* for errors. STOP means this sequence of chunks is complete. The 'wrote'
|
||||||
|
* argument is set to tell the caller how many bytes we actually passed to the
|
||||||
|
* client (for byte-counting and whatever).
|
||||||
|
*
|
||||||
|
* The states and the state-machine is further explained in the header file.
|
||||||
|
*/
|
||||||
|
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||||
|
char *datap,
|
||||||
|
ssize_t length,
|
||||||
|
ssize_t *wrote)
|
||||||
|
{
|
||||||
|
CURLcode result;
|
||||||
|
struct Curl_chunker *ch = &conn->proto.http->chunk;
|
||||||
|
int piece;
|
||||||
|
*wrote = 0; /* nothing yet */
|
||||||
|
|
||||||
|
while(length) {
|
||||||
|
switch(ch->state) {
|
||||||
|
case CHUNK_HEX:
|
||||||
|
if(isxdigit((int)*datap)) {
|
||||||
|
if(ch->hexindex < MAXNUM_SIZE) {
|
||||||
|
ch->hexbuffer[ch->hexindex] = *datap;
|
||||||
|
datap++;
|
||||||
|
length--;
|
||||||
|
ch->hexindex++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1; /* longer hex than we support */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* length and datap are unmodified */
|
||||||
|
ch->hexbuffer[ch->hexindex]=0;
|
||||||
|
ch->datasize=strtoul(ch->hexbuffer, NULL, 16);
|
||||||
|
ch->state = CHUNK_POSTHEX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHUNK_POSTHEX:
|
||||||
|
/* just a lame state waiting for CRLF to arrive */
|
||||||
|
if(*datap == '\r')
|
||||||
|
ch->state = CHUNK_CR;
|
||||||
|
length--;
|
||||||
|
datap++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHUNK_CR:
|
||||||
|
/* waiting for the LF */
|
||||||
|
if(*datap == '\n') {
|
||||||
|
/* we're now expecting data to come, unless size was zero! */
|
||||||
|
if(0 == ch->datasize) {
|
||||||
|
ch->state = CHUNK_STOP; /* stop reading! */
|
||||||
|
if(1 == length) {
|
||||||
|
/* This was the final byte, return right now */
|
||||||
|
return CHUNKE_STOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ch->state = CHUNK_DATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* previously we got a fake CR, go back to CR waiting! */
|
||||||
|
ch->state = CHUNK_CR;
|
||||||
|
datap++;
|
||||||
|
length--;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHUNK_DATA:
|
||||||
|
/* we get pure and fine data
|
||||||
|
|
||||||
|
We expect another 'datasize' of data. We have 'length' right now,
|
||||||
|
it can be more or less than 'datasize'. Get the smallest piece.
|
||||||
|
*/
|
||||||
|
piece = (ch->datasize >= length)?length:ch->datasize;
|
||||||
|
|
||||||
|
/* Write the data portion available */
|
||||||
|
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap, piece);
|
||||||
|
if(result)
|
||||||
|
return CHUNKE_WRITE_ERROR;
|
||||||
|
*wrote += piece;
|
||||||
|
|
||||||
|
ch->datasize -= piece; /* decrease amount left to expect */
|
||||||
|
datap += piece; /* move read pointer forward */
|
||||||
|
length -= piece; /* decrease space left in this round */
|
||||||
|
|
||||||
|
if(0 == ch->datasize)
|
||||||
|
/* end of data this round, go back to get a new size */
|
||||||
|
Curl_httpchunk_init(conn);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CHUNK_STOP:
|
||||||
|
/* If we arrive here, there is data left in the end of the buffer
|
||||||
|
even if there's no more chunks to read */
|
||||||
|
ch->dataleft = length;
|
||||||
|
return CHUNKE_STOP; /* return stop */
|
||||||
|
default:
|
||||||
|
return CHUNKE_STATE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CHUNKE_OK;
|
||||||
|
}
|
78
lib/http_chunks.h
Normal file
78
lib/http_chunks.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#ifndef __HTTP_CHUNKS_H
|
||||||
|
#define __HTTP_CHUNKS_H
|
||||||
|
/*****************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001, 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$
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* The longest possible hexadecimal number we support in a chunked transfer.
|
||||||
|
* Weird enoug, RFC2616 doesn't set a maximum size! Since we use strtoul()
|
||||||
|
* to convert it, we "only" support 2^32 bytes chunk data.
|
||||||
|
*/
|
||||||
|
#define MAXNUM_SIZE 16
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CHUNK_LOST, /* never use */
|
||||||
|
|
||||||
|
/* In this we await and buffer all hexadecimal digits until we get one
|
||||||
|
that isn't a hexadecimal digit. When done, we go POSTHEX */
|
||||||
|
CHUNK_HEX,
|
||||||
|
|
||||||
|
/* We have received the hexadecimal digit and we eat all characters until
|
||||||
|
we get a CRLF pair. When we see a CR we go to the CR state. */
|
||||||
|
CHUNK_POSTHEX,
|
||||||
|
|
||||||
|
/* A single CR has been found and we should get a LF right away in this
|
||||||
|
state or we go back to POSTHEX. When LF is received, we go to DATA.
|
||||||
|
If the size given was zero, we set state to STOP and return. */
|
||||||
|
CHUNK_CR,
|
||||||
|
|
||||||
|
/* We eat the amount of data specified. When done, we move back to the
|
||||||
|
HEX state. */
|
||||||
|
CHUNK_DATA,
|
||||||
|
|
||||||
|
/* This is mainly used to really mark that we're out of the game.
|
||||||
|
NOTE: that there's a 'dataleft' field in the struct that will tell how
|
||||||
|
many bytes that were not passed to the client in the end of the last
|
||||||
|
buffer! */
|
||||||
|
CHUNK_STOP,
|
||||||
|
|
||||||
|
CHUNK_LAST /* never use */
|
||||||
|
} ChunkyState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CHUNKE_STOP = -1,
|
||||||
|
CHUNKE_OK = 0,
|
||||||
|
CHUNKE_TOO_LONG_HEX = 1,
|
||||||
|
CHUNKE_WRITE_ERROR,
|
||||||
|
CHUNKE_STATE_ERROR,
|
||||||
|
CHUNKE_LAST
|
||||||
|
} CHUNKcode;
|
||||||
|
|
||||||
|
struct Curl_chunker {
|
||||||
|
char hexbuffer[ MAXNUM_SIZE + 1];
|
||||||
|
int hexindex;
|
||||||
|
ChunkyState state;
|
||||||
|
size_t datasize;
|
||||||
|
size_t dataleft; /* untouched data amount at the end of the last buffer */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
117
lib/ssluse.c
117
lib/ssluse.c
@@ -35,6 +35,7 @@
|
|||||||
#include "formdata.h" /* for the boundary function */
|
#include "formdata.h" /* for the boundary function */
|
||||||
|
|
||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
static char global_passwd[64];
|
static char global_passwd[64];
|
||||||
|
|
||||||
@@ -58,16 +59,93 @@ static int passwd_callback(char *buf, int num, int verify
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is *highly* inspired by (and parts are directly stolen
|
static
|
||||||
* from) source from the SSLeay package written by Eric Young
|
bool seed_enough(struct connectdata *conn, /* unused for now */
|
||||||
* (eay@cryptsoft.com). */
|
int nread)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_RAND_STATUS
|
||||||
|
/* only available in OpenSSL 0.9.5a and later */
|
||||||
|
if(RAND_status())
|
||||||
|
return TRUE;
|
||||||
|
#else
|
||||||
|
if(nread > 500)
|
||||||
|
/* this is a very silly decision to make */
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
return FALSE; /* not enough */
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int cert_stuff(struct UrlData *data,
|
int random_the_seed(struct connectdata *conn)
|
||||||
struct connectdata *conn,
|
{
|
||||||
|
char *buf = conn->data->buffer; /* point to the big buffer */
|
||||||
|
int nread=0;
|
||||||
|
|
||||||
|
/* Q: should we add support for a random file name as a libcurl option?
|
||||||
|
A: Yes */
|
||||||
|
#if 0
|
||||||
|
/* something like this */
|
||||||
|
nread += RAND_load_file(filename, number_of_bytes);
|
||||||
|
#endif
|
||||||
|
/* generates a default path for the random seed file */
|
||||||
|
buf[0]=0; /* blank it first */
|
||||||
|
RAND_file_name(buf, BUFSIZE);
|
||||||
|
if ( buf[0] ) {
|
||||||
|
/* we got a file name to try */
|
||||||
|
nread += RAND_load_file(buf, 16384);
|
||||||
|
if(seed_enough(conn, nread))
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RANDOM_FILE
|
||||||
|
nread += RAND_load_file(RANDOM_FILE, 16384);
|
||||||
|
if(seed_enough(conn, nread))
|
||||||
|
return nread;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_RAND_EGD) && defined(EGD_SOCKET)
|
||||||
|
/* only available in OpenSSL 0.9.5 and later */
|
||||||
|
/* EGD_SOCKET is set at configure time */
|
||||||
|
{
|
||||||
|
int ret = RAND_egd(EGD_SOCKET);
|
||||||
|
if(-1 != ret) {
|
||||||
|
nread += ret;
|
||||||
|
if(seed_enough(conn, nread))
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If we get here, it means we need to seed the PRNG using a "silly"
|
||||||
|
approach! */
|
||||||
|
#ifdef HAVE_RAND_SCREEN
|
||||||
|
/* This one gets a random value by reading the currently shown screen */
|
||||||
|
RAND_screen();
|
||||||
|
nread = 100; /* just a value */
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *area = Curl_FormBoundary();
|
||||||
|
if(!area)
|
||||||
|
return 3; /* out of memory */
|
||||||
|
|
||||||
|
len = strlen(area);
|
||||||
|
RAND_seed(area, len);
|
||||||
|
|
||||||
|
free(area); /* now remove the random junk */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
infof(conn->data, "Your connection is using a weak random seed!\n");
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int cert_stuff(struct connectdata *conn,
|
||||||
char *cert_file,
|
char *cert_file,
|
||||||
char *key_file)
|
char *key_file)
|
||||||
{
|
{
|
||||||
|
struct UrlData *data = conn->data;
|
||||||
if (cert_file != NULL) {
|
if (cert_file != NULL) {
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
X509 *x509;
|
X509 *x509;
|
||||||
@@ -123,9 +201,6 @@ int cert_stuff(struct UrlData *data,
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SSLEAY
|
|
||||||
static
|
static
|
||||||
int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
|
int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
|
||||||
{
|
{
|
||||||
@@ -156,28 +231,8 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
/* Lets get nice error messages */
|
/* Lets get nice error messages */
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
|
|
||||||
#ifdef HAVE_RAND_STATUS
|
/* Make funny stuff to get random input */
|
||||||
/* RAND_status() was introduced in OpenSSL 0.9.5 */
|
random_the_seed(conn);
|
||||||
if(0 == RAND_status())
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* We need to seed the PRNG properly! */
|
|
||||||
#ifdef HAVE_RAND_SCREEN
|
|
||||||
/* This one gets a random value by reading the currently shown screen */
|
|
||||||
RAND_screen();
|
|
||||||
#else
|
|
||||||
int len;
|
|
||||||
char *area = Curl_FormBoundary();
|
|
||||||
if(!area)
|
|
||||||
return 3; /* out of memory */
|
|
||||||
|
|
||||||
len = strlen(area);
|
|
||||||
|
|
||||||
RAND_seed(area, len);
|
|
||||||
|
|
||||||
free(area); /* now remove the random junk */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup all the global SSL stuff */
|
/* Setup all the global SSL stuff */
|
||||||
SSLeay_add_ssl_algorithms();
|
SSLeay_add_ssl_algorithms();
|
||||||
@@ -202,7 +257,7 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(data->cert) {
|
if(data->cert) {
|
||||||
if (!cert_stuff(data, conn, data->cert, data->cert)) {
|
if (!cert_stuff(conn, data->cert, data->cert)) {
|
||||||
failf(data, "couldn't use certificate!\n");
|
failf(data, "couldn't use certificate!\n");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
370
lib/telnet.c
370
lib/telnet.c
@@ -84,16 +84,16 @@
|
|||||||
|
|
||||||
#define SUBBUFSIZE 512
|
#define SUBBUFSIZE 512
|
||||||
|
|
||||||
#define SB_CLEAR() subpointer = subbuffer;
|
#define SB_CLEAR(x) x->subpointer = x->subbuffer;
|
||||||
#define SB_TERM() { subend = subpointer; SB_CLEAR(); }
|
#define SB_TERM(x) { x->subend = x->subpointer; SB_CLEAR(x); }
|
||||||
#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
|
#define SB_ACCUM(x,c) if (x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \
|
||||||
*subpointer++ = (c); \
|
*x->subpointer++ = (c); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SB_GET() ((*subpointer++)&0xff)
|
#define SB_GET(x) ((*x->subpointer++)&0xff)
|
||||||
#define SB_PEEK() ((*subpointer)&0xff)
|
#define SB_PEEK(x) ((*x->subpointer)&0xff)
|
||||||
#define SB_EOF() (subpointer >= subend)
|
#define SB_EOF(x) (x->subpointer >= x->subend)
|
||||||
#define SB_LEN() (subend - subpointer)
|
#define SB_LEN(x) (x->subend - x->subpointer)
|
||||||
|
|
||||||
static
|
static
|
||||||
void telrcv(struct connectdata *,
|
void telrcv(struct connectdata *,
|
||||||
@@ -113,14 +113,19 @@ static void printsub(struct UrlData *data,
|
|||||||
int direction, unsigned char *pointer, int length);
|
int direction, unsigned char *pointer, int length);
|
||||||
static void suboption(struct connectdata *);
|
static void suboption(struct connectdata *);
|
||||||
|
|
||||||
/* suboptions */
|
/* For negotiation compliant to RFC 1143 */
|
||||||
static char subbuffer[SUBBUFSIZE];
|
#define NO 0
|
||||||
static char *subpointer, *subend; /* buffer for sub-options */
|
#define YES 1
|
||||||
|
#define WANTYES 2
|
||||||
|
#define WANTNO 3
|
||||||
|
|
||||||
|
#define EMPTY 0
|
||||||
|
#define OPPOSITE 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Telnet receiver states for fsm
|
* Telnet receiver states for fsm
|
||||||
*/
|
*/
|
||||||
static enum
|
typedef enum
|
||||||
{
|
{
|
||||||
TS_DATA = 0,
|
TS_DATA = 0,
|
||||||
TS_IAC,
|
TS_IAC,
|
||||||
@@ -131,63 +136,76 @@ static enum
|
|||||||
TS_CR,
|
TS_CR,
|
||||||
TS_SB, /* sub-option collection */
|
TS_SB, /* sub-option collection */
|
||||||
TS_SE /* looking for sub-option end */
|
TS_SE /* looking for sub-option end */
|
||||||
} telrcv_state;
|
} TelnetReceive;
|
||||||
|
|
||||||
/* For negotiation compliant to RFC 1143 */
|
struct TELNET {
|
||||||
#define NO 0
|
int please_negotiate;
|
||||||
#define YES 1
|
int already_negotiated;
|
||||||
#define WANTYES 2
|
int us[256];
|
||||||
#define WANTNO 3
|
int usq[256];
|
||||||
|
int us_preferred[256];
|
||||||
|
int him[256];
|
||||||
|
int himq[256];
|
||||||
|
int him_preferred[256];
|
||||||
|
char *subopt_ttype; /* Set with suboption TTYPE */
|
||||||
|
char *subopt_xdisploc; /* Set with suboption XDISPLOC */
|
||||||
|
struct curl_slist *telnet_vars; /* Environment variables */
|
||||||
|
|
||||||
#define EMPTY 0
|
/* suboptions */
|
||||||
#define OPPOSITE 1
|
char subbuffer[SUBBUFSIZE];
|
||||||
|
char *subpointer, *subend; /* buffer for sub-options */
|
||||||
|
|
||||||
static int please_negotiate = 0;
|
TelnetReceive telrcv_state;
|
||||||
static int already_negotiated = 0;
|
};
|
||||||
static int us[256];
|
|
||||||
static int usq[256];
|
|
||||||
static int us_preferred[256];
|
|
||||||
static int him[256];
|
|
||||||
static int himq[256];
|
|
||||||
static int him_preferred[256];
|
|
||||||
|
|
||||||
static char *subopt_ttype = NULL; /* Set with suboption TTYPE */
|
|
||||||
static char *subopt_xdisploc = NULL; /* Set with suboption XDISPLOC */
|
|
||||||
static struct curl_slist *telnet_vars = NULL; /* Environment variables */
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void init_telnet(struct connectdata *conn)
|
CURLcode init_telnet(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
telrcv_state = TS_DATA;
|
struct TELNET *tn;
|
||||||
|
|
||||||
|
tn = (struct TELNET *)malloc(sizeof(struct TELNET));
|
||||||
|
if(!tn)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
conn->proto.telnet = (void *)tn; /* make us known */
|
||||||
|
|
||||||
|
memset(tn, 0, sizeof(struct TELNET));
|
||||||
|
|
||||||
|
tn->telrcv_state = TS_DATA;
|
||||||
|
|
||||||
/* Init suboptions */
|
/* Init suboptions */
|
||||||
SB_CLEAR();
|
SB_CLEAR(tn);
|
||||||
|
|
||||||
/* Set all options to NO */
|
/* Set all options to NO */
|
||||||
memset(us, NO, 256);
|
#if 0
|
||||||
memset(usq, NO, 256);
|
/* NO is zero => default fill pattern */
|
||||||
memset(us_preferred, NO, 256);
|
memset(tn->us, NO, 256);
|
||||||
memset(him, NO, 256);
|
memset(tn->usq, NO, 256);
|
||||||
memset(himq, NO, 256);
|
memset(tn->us_preferred, NO, 256);
|
||||||
memset(him_preferred, NO, 256);
|
memset(tn->him, NO, 256);
|
||||||
|
memset(tn->himq, NO, 256);
|
||||||
|
memset(tn->him_preferred, NO, 256);
|
||||||
|
#endif
|
||||||
/* Set the options we want by default */
|
/* Set the options we want by default */
|
||||||
us_preferred[TELOPT_BINARY] = YES;
|
tn->us_preferred[TELOPT_BINARY] = YES;
|
||||||
us_preferred[TELOPT_SGA] = YES;
|
tn->us_preferred[TELOPT_SGA] = YES;
|
||||||
him_preferred[TELOPT_BINARY] = YES;
|
tn->him_preferred[TELOPT_BINARY] = YES;
|
||||||
him_preferred[TELOPT_SGA] = YES;
|
tn->him_preferred[TELOPT_SGA] = YES;
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void negotiate(struct connectdata *conn)
|
static void negotiate(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
|
||||||
for(i = 0;i < NTELOPTS;i++)
|
for(i = 0;i < NTELOPTS;i++)
|
||||||
{
|
{
|
||||||
if(us_preferred[i] == YES)
|
if(tn->us_preferred[i] == YES)
|
||||||
set_local_option(conn, i, YES);
|
set_local_option(conn, i, YES);
|
||||||
|
|
||||||
if(him_preferred[i] == YES)
|
if(tn->him_preferred[i] == YES)
|
||||||
set_remote_option(conn, i, YES);
|
set_remote_option(conn, i, YES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,12 +265,13 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
|
|||||||
static
|
static
|
||||||
void set_remote_option(struct connectdata *conn, int option, int newstate)
|
void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||||
{
|
{
|
||||||
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
if(newstate == YES)
|
if(newstate == YES)
|
||||||
{
|
{
|
||||||
switch(him[option])
|
switch(tn->him[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
him[option] = WANTYES;
|
tn->him[option] = WANTYES;
|
||||||
send_negotiation(conn, DO, option);
|
send_negotiation(conn, DO, option);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -261,11 +280,11 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Already negotiating for YES, queue the request */
|
/* Already negotiating for YES, queue the request */
|
||||||
himq[option] = OPPOSITE;
|
tn->himq[option] = OPPOSITE;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
/* Error: already queued an enable request */
|
/* Error: already queued an enable request */
|
||||||
@@ -274,13 +293,13 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Error: already negotiating for enable */
|
/* Error: already negotiating for enable */
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -288,34 +307,34 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
|||||||
}
|
}
|
||||||
else /* NO */
|
else /* NO */
|
||||||
{
|
{
|
||||||
switch(him[option])
|
switch(tn->him[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
/* Already disabled */
|
/* Already disabled */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YES:
|
case YES:
|
||||||
him[option] = WANTNO;
|
tn->him[option] = WANTNO;
|
||||||
send_negotiation(conn, DONT, option);
|
send_negotiation(conn, DONT, option);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Already negotiating for NO */
|
/* Already negotiating for NO */
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
himq[option] = OPPOSITE;
|
tn->himq[option] = OPPOSITE;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
break;
|
break;
|
||||||
@@ -328,12 +347,13 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
|||||||
static
|
static
|
||||||
void rec_will(struct connectdata *conn, int option)
|
void rec_will(struct connectdata *conn, int option)
|
||||||
{
|
{
|
||||||
switch(him[option])
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
switch(tn->him[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
if(him_preferred[option] == YES)
|
if(tn->him_preferred[option] == YES)
|
||||||
{
|
{
|
||||||
him[option] = YES;
|
tn->him[option] = YES;
|
||||||
send_negotiation(conn, DO, option);
|
send_negotiation(conn, DO, option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -347,29 +367,29 @@ void rec_will(struct connectdata *conn, int option)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Error: DONT answered by WILL */
|
/* Error: DONT answered by WILL */
|
||||||
him[option] = NO;
|
tn->him[option] = NO;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
/* Error: DONT answered by WILL */
|
/* Error: DONT answered by WILL */
|
||||||
him[option] = YES;
|
tn->him[option] = YES;
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
him[option] = YES;
|
tn->him[option] = YES;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
him[option] = WANTNO;
|
tn->him[option] = WANTNO;
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
send_negotiation(conn, DONT, option);
|
send_negotiation(conn, DONT, option);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -380,41 +400,42 @@ void rec_will(struct connectdata *conn, int option)
|
|||||||
static
|
static
|
||||||
void rec_wont(struct connectdata *conn, int option)
|
void rec_wont(struct connectdata *conn, int option)
|
||||||
{
|
{
|
||||||
switch(him[option])
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
switch(tn->him[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
/* Already disabled */
|
/* Already disabled */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YES:
|
case YES:
|
||||||
him[option] = NO;
|
tn->him[option] = NO;
|
||||||
send_negotiation(conn, DONT, option);
|
send_negotiation(conn, DONT, option);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
him[option] = NO;
|
tn->him[option] = NO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
him[option] = WANTYES;
|
tn->him[option] = WANTYES;
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
send_negotiation(conn, DO, option);
|
send_negotiation(conn, DO, option);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(himq[option])
|
switch(tn->himq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
him[option] = NO;
|
tn->him[option] = NO;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
him[option] = NO;
|
tn->him[option] = NO;
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -423,12 +444,13 @@ void rec_wont(struct connectdata *conn, int option)
|
|||||||
|
|
||||||
void set_local_option(struct connectdata *conn, int option, int newstate)
|
void set_local_option(struct connectdata *conn, int option, int newstate)
|
||||||
{
|
{
|
||||||
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
if(newstate == YES)
|
if(newstate == YES)
|
||||||
{
|
{
|
||||||
switch(us[option])
|
switch(tn->us[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
us[option] = WANTYES;
|
tn->us[option] = WANTYES;
|
||||||
send_negotiation(conn, WILL, option);
|
send_negotiation(conn, WILL, option);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -437,11 +459,11 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Already negotiating for YES, queue the request */
|
/* Already negotiating for YES, queue the request */
|
||||||
usq[option] = OPPOSITE;
|
tn->usq[option] = OPPOSITE;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
/* Error: already queued an enable request */
|
/* Error: already queued an enable request */
|
||||||
@@ -450,13 +472,13 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Error: already negotiating for enable */
|
/* Error: already negotiating for enable */
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
usq[option] = EMPTY;
|
tn->usq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -464,34 +486,34 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
|||||||
}
|
}
|
||||||
else /* NO */
|
else /* NO */
|
||||||
{
|
{
|
||||||
switch(us[option])
|
switch(tn->us[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
/* Already disabled */
|
/* Already disabled */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YES:
|
case YES:
|
||||||
us[option] = WANTNO;
|
tn->us[option] = WANTNO;
|
||||||
send_negotiation(conn, WONT, option);
|
send_negotiation(conn, WONT, option);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Already negotiating for NO */
|
/* Already negotiating for NO */
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
usq[option] = EMPTY;
|
tn->usq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
usq[option] = OPPOSITE;
|
tn->usq[option] = OPPOSITE;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
break;
|
break;
|
||||||
@@ -504,12 +526,13 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
|||||||
static
|
static
|
||||||
void rec_do(struct connectdata *conn, int option)
|
void rec_do(struct connectdata *conn, int option)
|
||||||
{
|
{
|
||||||
switch(us[option])
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
switch(tn->us[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
if(us_preferred[option] == YES)
|
if(tn->us_preferred[option] == YES)
|
||||||
{
|
{
|
||||||
us[option] = YES;
|
tn->us[option] = YES;
|
||||||
send_negotiation(conn, WILL, option);
|
send_negotiation(conn, WILL, option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -523,29 +546,29 @@ void rec_do(struct connectdata *conn, int option)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
/* Error: DONT answered by WILL */
|
/* Error: DONT answered by WILL */
|
||||||
us[option] = NO;
|
tn->us[option] = NO;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
/* Error: DONT answered by WILL */
|
/* Error: DONT answered by WILL */
|
||||||
us[option] = YES;
|
tn->us[option] = YES;
|
||||||
usq[option] = EMPTY;
|
tn->usq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
us[option] = YES;
|
tn->us[option] = YES;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
us[option] = WANTNO;
|
tn->us[option] = WANTNO;
|
||||||
himq[option] = EMPTY;
|
tn->himq[option] = EMPTY;
|
||||||
send_negotiation(conn, WONT, option);
|
send_negotiation(conn, WONT, option);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -556,41 +579,42 @@ void rec_do(struct connectdata *conn, int option)
|
|||||||
static
|
static
|
||||||
void rec_dont(struct connectdata *conn, int option)
|
void rec_dont(struct connectdata *conn, int option)
|
||||||
{
|
{
|
||||||
switch(us[option])
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
switch(tn->us[option])
|
||||||
{
|
{
|
||||||
case NO:
|
case NO:
|
||||||
/* Already disabled */
|
/* Already disabled */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case YES:
|
case YES:
|
||||||
us[option] = NO;
|
tn->us[option] = NO;
|
||||||
send_negotiation(conn, WONT, option);
|
send_negotiation(conn, WONT, option);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTNO:
|
case WANTNO:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
us[option] = NO;
|
tn->us[option] = NO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
us[option] = WANTYES;
|
tn->us[option] = WANTYES;
|
||||||
usq[option] = EMPTY;
|
tn->usq[option] = EMPTY;
|
||||||
send_negotiation(conn, WILL, option);
|
send_negotiation(conn, WILL, option);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WANTYES:
|
case WANTYES:
|
||||||
switch(usq[option])
|
switch(tn->usq[option])
|
||||||
{
|
{
|
||||||
case EMPTY:
|
case EMPTY:
|
||||||
us[option] = NO;
|
tn->us[option] = NO;
|
||||||
break;
|
break;
|
||||||
case OPPOSITE:
|
case OPPOSITE:
|
||||||
us[option] = NO;
|
tn->us[option] = NO;
|
||||||
usq[option] = EMPTY;
|
tn->usq[option] = EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -717,6 +741,7 @@ static int check_telnet_options(struct connectdata *conn)
|
|||||||
char option_arg[256];
|
char option_arg[256];
|
||||||
char *buf;
|
char *buf;
|
||||||
struct UrlData *data = conn->data;
|
struct UrlData *data = conn->data;
|
||||||
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
|
||||||
/* Add the user name as an environment variable if it
|
/* Add the user name as an environment variable if it
|
||||||
was given on the command line */
|
was given on the command line */
|
||||||
@@ -724,9 +749,9 @@ static int check_telnet_options(struct connectdata *conn)
|
|||||||
{
|
{
|
||||||
char *buf = malloc(256);
|
char *buf = malloc(256);
|
||||||
sprintf(buf, "USER,%s", data->user);
|
sprintf(buf, "USER,%s", data->user);
|
||||||
telnet_vars = curl_slist_append(telnet_vars, buf);
|
tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
|
||||||
|
|
||||||
us_preferred[TELOPT_NEW_ENVIRON] = YES;
|
tn->us_preferred[TELOPT_NEW_ENVIRON] = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(head = data->telnet_options; head; head=head->next) {
|
for(head = data->telnet_options; head; head=head->next) {
|
||||||
@@ -735,15 +760,15 @@ static int check_telnet_options(struct connectdata *conn)
|
|||||||
|
|
||||||
/* Terminal type */
|
/* Terminal type */
|
||||||
if(strequal(option_keyword, "TTYPE")) {
|
if(strequal(option_keyword, "TTYPE")) {
|
||||||
subopt_ttype = option_arg;
|
tn->subopt_ttype = option_arg;
|
||||||
us_preferred[TELOPT_TTYPE] = YES;
|
tn->us_preferred[TELOPT_TTYPE] = YES;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display variable */
|
/* Display variable */
|
||||||
if(strequal(option_keyword, "XDISPLOC")) {
|
if(strequal(option_keyword, "XDISPLOC")) {
|
||||||
subopt_xdisploc = option_arg;
|
tn->subopt_xdisploc = option_arg;
|
||||||
us_preferred[TELOPT_XDISPLOC] = YES;
|
tn->us_preferred[TELOPT_XDISPLOC] = YES;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,8 +777,8 @@ static int check_telnet_options(struct connectdata *conn)
|
|||||||
buf = strdup(option_arg);
|
buf = strdup(option_arg);
|
||||||
if(!buf)
|
if(!buf)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
telnet_vars = curl_slist_append(telnet_vars, buf);
|
tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
|
||||||
us_preferred[TELOPT_NEW_ENVIRON] = YES;
|
tn->us_preferred[TELOPT_NEW_ENVIRON] = YES;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,7 +798,6 @@ static int check_telnet_options(struct connectdata *conn)
|
|||||||
*
|
*
|
||||||
* Look at the sub-option buffer, and try to be helpful to the other
|
* Look at the sub-option buffer, and try to be helpful to the other
|
||||||
* side.
|
* side.
|
||||||
* No suboptions are supported yet.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void suboption(struct connectdata *conn)
|
static void suboption(struct connectdata *conn)
|
||||||
@@ -786,22 +810,23 @@ static void suboption(struct connectdata *conn)
|
|||||||
char varname[128];
|
char varname[128];
|
||||||
char varval[128];
|
char varval[128];
|
||||||
struct UrlData *data = conn->data;
|
struct UrlData *data = conn->data;
|
||||||
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
|
||||||
printsub(data, '<', (unsigned char *)subbuffer, SB_LEN()+2);
|
printsub(data, '<', (unsigned char *)tn->subbuffer, SB_LEN(tn)+2);
|
||||||
switch (subchar = SB_GET()) {
|
switch (subchar = SB_GET(tn)) {
|
||||||
case TELOPT_TTYPE:
|
case TELOPT_TTYPE:
|
||||||
len = strlen(subopt_ttype) + 4 + 2;
|
len = strlen(tn->subopt_ttype) + 4 + 2;
|
||||||
snprintf((char *)temp, sizeof(temp),
|
snprintf((char *)temp, sizeof(temp),
|
||||||
"%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
|
"%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
|
||||||
TELQUAL_IS, subopt_ttype, IAC, SE);
|
TELQUAL_IS, tn->subopt_ttype, IAC, SE);
|
||||||
swrite(conn->firstsocket, temp, len);
|
swrite(conn->firstsocket, temp, len);
|
||||||
printsub(data, '>', &temp[2], len-2);
|
printsub(data, '>', &temp[2], len-2);
|
||||||
break;
|
break;
|
||||||
case TELOPT_XDISPLOC:
|
case TELOPT_XDISPLOC:
|
||||||
len = strlen(subopt_xdisploc) + 4 + 2;
|
len = strlen(tn->subopt_xdisploc) + 4 + 2;
|
||||||
snprintf((char *)temp, sizeof(temp),
|
snprintf((char *)temp, sizeof(temp),
|
||||||
"%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
|
"%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
|
||||||
TELQUAL_IS, subopt_xdisploc, IAC, SE);
|
TELQUAL_IS, tn->subopt_xdisploc, IAC, SE);
|
||||||
swrite(conn->firstsocket, temp, len);
|
swrite(conn->firstsocket, temp, len);
|
||||||
printsub(data, '>', &temp[2], len-2);
|
printsub(data, '>', &temp[2], len-2);
|
||||||
break;
|
break;
|
||||||
@@ -810,7 +835,7 @@ static void suboption(struct connectdata *conn)
|
|||||||
"%c%c%c%c", IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS);
|
"%c%c%c%c", IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS);
|
||||||
len = 4;
|
len = 4;
|
||||||
|
|
||||||
for(v = telnet_vars;v;v = v->next) {
|
for(v = tn->telnet_vars;v;v = v->next) {
|
||||||
tmplen = (strlen(v->data) + 1);
|
tmplen = (strlen(v->data) + 1);
|
||||||
/* Add the variable only if it fits */
|
/* Add the variable only if it fits */
|
||||||
if(len + tmplen < sizeof(temp)-6) {
|
if(len + tmplen < sizeof(temp)-6) {
|
||||||
@@ -839,15 +864,16 @@ void telrcv(struct connectdata *conn,
|
|||||||
unsigned char c;
|
unsigned char c;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
struct UrlData *data = conn->data;
|
struct UrlData *data = conn->data;
|
||||||
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
|
||||||
while(count--)
|
while(count--)
|
||||||
{
|
{
|
||||||
c = inbuf[index++];
|
c = inbuf[index++];
|
||||||
|
|
||||||
switch (telrcv_state)
|
switch (tn->telrcv_state)
|
||||||
{
|
{
|
||||||
case TS_CR:
|
case TS_CR:
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
{
|
{
|
||||||
break; /* Ignore \0 after CR */
|
break; /* Ignore \0 after CR */
|
||||||
@@ -859,12 +885,12 @@ void telrcv(struct connectdata *conn,
|
|||||||
case TS_DATA:
|
case TS_DATA:
|
||||||
if (c == IAC)
|
if (c == IAC)
|
||||||
{
|
{
|
||||||
telrcv_state = TS_IAC;
|
tn->telrcv_state = TS_IAC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(c == '\r')
|
else if(c == '\r')
|
||||||
{
|
{
|
||||||
telrcv_state = TS_CR;
|
tn->telrcv_state = TS_CR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
|
||||||
@@ -875,20 +901,20 @@ void telrcv(struct connectdata *conn,
|
|||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case WILL:
|
case WILL:
|
||||||
telrcv_state = TS_WILL;
|
tn->telrcv_state = TS_WILL;
|
||||||
continue;
|
continue;
|
||||||
case WONT:
|
case WONT:
|
||||||
telrcv_state = TS_WONT;
|
tn->telrcv_state = TS_WONT;
|
||||||
continue;
|
continue;
|
||||||
case DO:
|
case DO:
|
||||||
telrcv_state = TS_DO;
|
tn->telrcv_state = TS_DO;
|
||||||
continue;
|
continue;
|
||||||
case DONT:
|
case DONT:
|
||||||
telrcv_state = TS_DONT;
|
tn->telrcv_state = TS_DONT;
|
||||||
continue;
|
continue;
|
||||||
case SB:
|
case SB:
|
||||||
SB_CLEAR();
|
SB_CLEAR(tn);
|
||||||
telrcv_state = TS_SB;
|
tn->telrcv_state = TS_SB;
|
||||||
continue;
|
continue;
|
||||||
case IAC:
|
case IAC:
|
||||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
|
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
|
||||||
@@ -900,45 +926,45 @@ void telrcv(struct connectdata *conn,
|
|||||||
printoption(data, "RCVD", IAC, c);
|
printoption(data, "RCVD", IAC, c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TS_WILL:
|
case TS_WILL:
|
||||||
printoption(data, "RCVD", WILL, c);
|
printoption(data, "RCVD", WILL, c);
|
||||||
please_negotiate = 1;
|
tn->please_negotiate = 1;
|
||||||
rec_will(conn, c);
|
rec_will(conn, c);
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TS_WONT:
|
case TS_WONT:
|
||||||
printoption(data, "RCVD", WONT, c);
|
printoption(data, "RCVD", WONT, c);
|
||||||
please_negotiate = 1;
|
tn->please_negotiate = 1;
|
||||||
rec_wont(conn, c);
|
rec_wont(conn, c);
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TS_DO:
|
case TS_DO:
|
||||||
printoption(data, "RCVD", DO, c);
|
printoption(data, "RCVD", DO, c);
|
||||||
please_negotiate = 1;
|
tn->please_negotiate = 1;
|
||||||
rec_do(conn, c);
|
rec_do(conn, c);
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TS_DONT:
|
case TS_DONT:
|
||||||
printoption(data, "RCVD", DONT, c);
|
printoption(data, "RCVD", DONT, c);
|
||||||
please_negotiate = 1;
|
tn->please_negotiate = 1;
|
||||||
rec_dont(conn, c);
|
rec_dont(conn, c);
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case TS_SB:
|
case TS_SB:
|
||||||
if (c == IAC)
|
if (c == IAC)
|
||||||
{
|
{
|
||||||
telrcv_state = TS_SE;
|
tn->telrcv_state = TS_SE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SB_ACCUM(c);
|
SB_ACCUM(tn,c);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -959,27 +985,27 @@ void telrcv(struct connectdata *conn,
|
|||||||
* we terminate the suboption, and process the
|
* we terminate the suboption, and process the
|
||||||
* partial suboption if we can.
|
* partial suboption if we can.
|
||||||
*/
|
*/
|
||||||
SB_ACCUM((unsigned char)IAC);
|
SB_ACCUM(tn, (unsigned char)IAC);
|
||||||
SB_ACCUM(c);
|
SB_ACCUM(tn, c);
|
||||||
subpointer -= 2;
|
tn->subpointer -= 2;
|
||||||
SB_TERM();
|
SB_TERM(tn);
|
||||||
|
|
||||||
printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
|
printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
|
||||||
suboption(conn); /* handle sub-option */
|
suboption(conn); /* handle sub-option */
|
||||||
telrcv_state = TS_IAC;
|
tn->telrcv_state = TS_IAC;
|
||||||
goto process_iac;
|
goto process_iac;
|
||||||
}
|
}
|
||||||
SB_ACCUM(c);
|
SB_ACCUM(tn,c);
|
||||||
telrcv_state = TS_SB;
|
tn->telrcv_state = TS_SB;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SB_ACCUM((unsigned char)IAC);
|
SB_ACCUM(tn, (unsigned char)IAC);
|
||||||
SB_ACCUM((unsigned char)SE);
|
SB_ACCUM(tn, (unsigned char)SE);
|
||||||
subpointer -= 2;
|
tn->subpointer -= 2;
|
||||||
SB_TERM();
|
SB_TERM(tn);
|
||||||
suboption(conn); /* handle sub-option */
|
suboption(conn); /* handle sub-option */
|
||||||
telrcv_state = TS_DATA;
|
tn->telrcv_state = TS_DATA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -988,7 +1014,12 @@ void telrcv(struct connectdata *conn,
|
|||||||
|
|
||||||
CURLcode Curl_telnet_done(struct connectdata *conn)
|
CURLcode Curl_telnet_done(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
curl_slist_free_all(telnet_vars);
|
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
curl_slist_free_all(tn->telnet_vars);
|
||||||
|
|
||||||
|
free(conn->proto.telnet);
|
||||||
|
conn->proto.telnet = NULL;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,8 +1034,13 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
bool keepon = TRUE;
|
bool keepon = TRUE;
|
||||||
char *buf = data->buffer;
|
char *buf = data->buffer;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
|
struct TELNET *tn;
|
||||||
|
|
||||||
init_telnet(conn);
|
code = init_telnet(conn);
|
||||||
|
if(code)
|
||||||
|
return code;
|
||||||
|
|
||||||
|
tn = (struct TELNET *)conn->proto.telnet;
|
||||||
|
|
||||||
code = check_telnet_options(conn);
|
code = check_telnet_options(conn);
|
||||||
if(code)
|
if(code)
|
||||||
@@ -1060,9 +1096,9 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
|||||||
/* Negotiate if the peer has started negotiating,
|
/* Negotiate if the peer has started negotiating,
|
||||||
otherwise don't. We don't want to speak telnet with
|
otherwise don't. We don't want to speak telnet with
|
||||||
non-telnet servers, like POP or SMTP. */
|
non-telnet servers, like POP or SMTP. */
|
||||||
if(please_negotiate && !already_negotiated) {
|
if(tn->please_negotiate && !tn->already_negotiated) {
|
||||||
negotiate(conn);
|
negotiate(conn);
|
||||||
already_negotiated = 1;
|
tn->already_negotiated = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -89,6 +89,7 @@
|
|||||||
#include "getpass.h"
|
#include "getpass.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "getdate.h"
|
#include "getdate.h"
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -337,6 +338,18 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
return urg;
|
return urg;
|
||||||
|
|
||||||
data->header_size += p - data->headerbuff;
|
data->header_size += p - data->headerbuff;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* end-of-headers.
|
||||||
|
*
|
||||||
|
* If we requested a "no body" and this isn't a "close"
|
||||||
|
* connection, this is a good time to get out and return
|
||||||
|
* home.
|
||||||
|
*/
|
||||||
|
if(!conn->bits.close && data->bits.no_body)
|
||||||
|
return CURLE_OK;
|
||||||
|
|
||||||
break; /* exit header line loop */
|
break; /* exit header line loop */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,8 +378,10 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
}
|
}
|
||||||
/* check for Content-Length: header lines to get size */
|
/* check for Content-Length: header lines to get size */
|
||||||
if (strnequal("Content-Length", p, 14) &&
|
if (strnequal("Content-Length", p, 14) &&
|
||||||
sscanf (p+14, ": %ld", &contentlength))
|
sscanf (p+14, ": %ld", &contentlength)) {
|
||||||
conn->size = contentlength;
|
conn->size = contentlength;
|
||||||
|
Curl_pgrsSetDownloadSize(data, contentlength);
|
||||||
|
}
|
||||||
else if (strnequal("Connection: close", p,
|
else if (strnequal("Connection: close", p,
|
||||||
strlen("Connection: close"))) {
|
strlen("Connection: close"))) {
|
||||||
/*
|
/*
|
||||||
@@ -377,10 +392,25 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
*/
|
*/
|
||||||
conn->bits.close = TRUE; /* close when done */
|
conn->bits.close = TRUE; /* close when done */
|
||||||
}
|
}
|
||||||
|
else if (strnequal("Transfer-Encoding: chunked", p,
|
||||||
|
strlen("Transfer-Encoding: chunked"))) {
|
||||||
|
/*
|
||||||
|
* [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
|
||||||
|
* means that the server will send a series of "chunks". Each
|
||||||
|
* chunk starts with line with info (including size of the
|
||||||
|
* coming block) (terminated with CRLF), then a block of data
|
||||||
|
* with the previously mentioned size. There can be any amount
|
||||||
|
* of chunks, and a chunk-data set to zero signals the
|
||||||
|
* end-of-chunks. */
|
||||||
|
conn->bits.chunk = TRUE; /* chunks coming our way */
|
||||||
|
|
||||||
|
/* init our chunky engine */
|
||||||
|
Curl_httpchunk_init(conn);
|
||||||
|
}
|
||||||
else if (strnequal("Content-Range", p, 13)) {
|
else if (strnequal("Content-Range", p, 13)) {
|
||||||
if (sscanf (p+13, ": bytes %d-", &offset) ||
|
if (sscanf (p+13, ": bytes %d-", &offset) ||
|
||||||
sscanf (p+13, ": bytes: %d-", &offset)) {
|
sscanf (p+13, ": bytes: %d-", &offset)) {
|
||||||
/* This second format was added August 1st by Igor
|
/* This second format was added August 1st 2000 by Igor
|
||||||
Khristophorov since Sun's webserver JavaWebServer/1.1.1
|
Khristophorov since Sun's webserver JavaWebServer/1.1.1
|
||||||
obviously sends the header this way! :-( */
|
obviously sends the header this way! :-( */
|
||||||
if (data->resume_from == offset) {
|
if (data->resume_from == offset) {
|
||||||
@@ -457,7 +487,7 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
|
|
||||||
if(0 == bodywrites) {
|
if(0 == bodywrites) {
|
||||||
/* These checks are only made the first time we are about to
|
/* These checks are only made the first time we are about to
|
||||||
write a chunk of the body */
|
write a piece of the body */
|
||||||
if(conn->protocol&PROT_HTTP) {
|
if(conn->protocol&PROT_HTTP) {
|
||||||
/* HTTP-only checks */
|
/* HTTP-only checks */
|
||||||
if (data->newurl) {
|
if (data->newurl) {
|
||||||
@@ -514,6 +544,29 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
} /* this is the first time we write a body part */
|
} /* this is the first time we write a body part */
|
||||||
bodywrites++;
|
bodywrites++;
|
||||||
|
|
||||||
|
if(conn->bits.chunk) {
|
||||||
|
/*
|
||||||
|
* Bless me father for I have sinned. Here comes a chunked
|
||||||
|
* transfer flying and we need to decode this properly. While
|
||||||
|
* the name says read, this function both reads and writes away
|
||||||
|
* the data. The returned 'nread' holds the number of actual
|
||||||
|
* data it wrote to the client. */
|
||||||
|
CHUNKcode res =
|
||||||
|
Curl_httpchunk_read(conn, str, nread, &nread);
|
||||||
|
|
||||||
|
if(CHUNKE_OK < res)
|
||||||
|
return CURLE_READ_ERROR;
|
||||||
|
else if(CHUNKE_STOP == res) {
|
||||||
|
/* we're done reading chunks! */
|
||||||
|
keepon &= ~KEEP_READ; /* read no more */
|
||||||
|
|
||||||
|
/* There are now possibly bytes at the end of the str buffer
|
||||||
|
that weren't written to the client, but we don't care
|
||||||
|
about them right now. */
|
||||||
|
}
|
||||||
|
/* If it returned OK, we just keep going */
|
||||||
|
}
|
||||||
|
|
||||||
if(conn->maxdownload &&
|
if(conn->maxdownload &&
|
||||||
(bytecount + nread >= conn->maxdownload)) {
|
(bytecount + nread >= conn->maxdownload)) {
|
||||||
nread = conn->maxdownload - bytecount;
|
nread = conn->maxdownload - bytecount;
|
||||||
@@ -526,9 +579,12 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
|
|
||||||
Curl_pgrsSetDownloadCounter(data, (double)bytecount);
|
Curl_pgrsSetDownloadCounter(data, (double)bytecount);
|
||||||
|
|
||||||
|
if(! conn->bits.chunk) {
|
||||||
|
/* If this is chunky transfer, it was already written */
|
||||||
urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread);
|
urg = Curl_client_write(data, CLIENTWRITE_BODY, str, nread);
|
||||||
if(urg)
|
if(urg)
|
||||||
return urg;
|
return urg;
|
||||||
|
}
|
||||||
|
|
||||||
} /* if (! header and data to read ) */
|
} /* if (! header and data to read ) */
|
||||||
} /* if( read from socket ) */
|
} /* if( read from socket ) */
|
||||||
@@ -625,8 +681,6 @@ _Transfer(struct connectdata *c_conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*func_T)(void);
|
|
||||||
|
|
||||||
CURLcode curl_transfer(CURL *curl)
|
CURLcode curl_transfer(CURL *curl)
|
||||||
{
|
{
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
|
44
lib/url.c
44
lib/url.c
@@ -982,6 +982,11 @@ static CURLcode _connect(CURL *curl,
|
|||||||
*in_connect = NULL; /* clear the pointer */
|
*in_connect = NULL; /* clear the pointer */
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
/* We must set the return variable as soon as possible, so that our
|
||||||
|
parent can cleanup any possible allocs we may have done before
|
||||||
|
any failure */
|
||||||
|
*in_connect = conn;
|
||||||
|
|
||||||
/* we have to init the struct */
|
/* we have to init the struct */
|
||||||
memset(conn, 0, sizeof(struct connectdata));
|
memset(conn, 0, sizeof(struct connectdata));
|
||||||
|
|
||||||
@@ -994,6 +999,12 @@ static CURLcode _connect(CURL *curl,
|
|||||||
conn->secondarysocket = -1; /* no file descriptor */
|
conn->secondarysocket = -1; /* no file descriptor */
|
||||||
conn->connectindex = -1; /* no index */
|
conn->connectindex = -1; /* no index */
|
||||||
|
|
||||||
|
/* Default protocol-indepent behaveiour doesn't support persistant
|
||||||
|
connections, so we set this to force-close. Protocols that support
|
||||||
|
this need to set this to FALSE in their "curl_do" functions. */
|
||||||
|
conn->bits.close = TRUE;
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************
|
/***********************************************************
|
||||||
* We need to allocate memory to store the path in. We get the size of the
|
* We need to allocate memory to store the path in. We get the size of the
|
||||||
* full URL to be sure, and we need to make it at least 256 bytes since
|
* full URL to be sure, and we need to make it at least 256 bytes since
|
||||||
@@ -1425,13 +1436,20 @@ static CURLcode _connect(CURL *curl,
|
|||||||
else if (strequal(conn->protostr, "FILE")) {
|
else if (strequal(conn->protostr, "FILE")) {
|
||||||
conn->protocol |= PROT_FILE;
|
conn->protocol |= PROT_FILE;
|
||||||
|
|
||||||
conn->curl_do = file;
|
conn->curl_do = Curl_file;
|
||||||
/* no done() function */
|
/* no done() function */
|
||||||
|
|
||||||
|
/* anyway, this is supposed to be the connect function so we better
|
||||||
|
at least check that the file is present here! */
|
||||||
|
result = Curl_file_connect(conn);
|
||||||
|
|
||||||
|
/* Setup a "faked" transfer that'll do nothing */
|
||||||
|
if(CURLE_OK == result) {
|
||||||
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
|
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
|
||||||
-1, NULL); /* no upload */
|
-1, NULL); /* no upload */
|
||||||
|
}
|
||||||
|
|
||||||
return CURLE_OK;
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* We fell through all checks and thus we don't support the specified
|
/* We fell through all checks and thus we don't support the specified
|
||||||
@@ -1582,7 +1600,6 @@ static CURLcode _connect(CURL *curl,
|
|||||||
*/
|
*/
|
||||||
ConnectionStore(data, conn);
|
ConnectionStore(data, conn);
|
||||||
}
|
}
|
||||||
*in_connect = conn;
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Resolve the name of the server or proxy
|
* Resolve the name of the server or proxy
|
||||||
@@ -1779,30 +1796,15 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect,
|
|||||||
if(CURLE_OK != code) {
|
if(CURLE_OK != code) {
|
||||||
/* We're not allowed to return failure with memory left allocated
|
/* We're not allowed to return failure with memory left allocated
|
||||||
in the connectdata struct, free those here */
|
in the connectdata struct, free those here */
|
||||||
|
conn = (struct connectdata *)*in_connect;
|
||||||
|
if(conn) {
|
||||||
struct UrlData *data;
|
struct UrlData *data;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
conn = (struct connectdata *)*in_connect;
|
|
||||||
data = conn->data;
|
data = conn->data;
|
||||||
#if 0
|
|
||||||
if(conn) {
|
|
||||||
if(conn->path)
|
|
||||||
free(conn->path);
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
if(conn->hp)
|
|
||||||
freeaddrinfo(conn->hp);
|
|
||||||
#else
|
|
||||||
if(conn->hostent_buf)
|
|
||||||
free(conn->hostent_buf);
|
|
||||||
#endif
|
|
||||||
free(conn);
|
|
||||||
*in_connect=NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
index = conn->connectindex; /* get the index */
|
index = conn->connectindex; /* get the index */
|
||||||
curl_disconnect(conn); /* close the connection */
|
curl_disconnect(conn); /* close the connection */
|
||||||
data->connects[index]=NULL; /* clear the pointer */
|
data->connects[index]=NULL; /* clear the pointer */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@@ -79,6 +79,8 @@
|
|||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||||
|
|
||||||
/* Download buffer size, keep it fairly big for speed reasons */
|
/* Download buffer size, keep it fairly big for speed reasons */
|
||||||
#define BUFSIZE (1024*50)
|
#define BUFSIZE (1024*50)
|
||||||
|
|
||||||
@@ -167,6 +169,8 @@ struct HTTP {
|
|||||||
struct Form form;
|
struct Form form;
|
||||||
size_t (*storefread)(char *, size_t , size_t , FILE *);
|
size_t (*storefread)(char *, size_t , size_t , FILE *);
|
||||||
FILE *in;
|
FILE *in;
|
||||||
|
|
||||||
|
struct Curl_chunker chunk;
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -183,12 +187,20 @@ struct FTP {
|
|||||||
char *entrypath; /* the PWD reply when we logged on */
|
char *entrypath; /* the PWD reply when we logged on */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* FILE unique setup
|
||||||
|
***************************************************************************/
|
||||||
|
struct FILE {
|
||||||
|
int fd; /* open file descriptor to read from! */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Boolean values that concerns this connection.
|
* Boolean values that concerns this connection.
|
||||||
*/
|
*/
|
||||||
struct ConnectBits {
|
struct ConnectBits {
|
||||||
bool close; /* if set, we close the connection after this request */
|
bool close; /* if set, we close the connection after this request */
|
||||||
bool reuse; /* if set, this is a re-used connection */
|
bool reuse; /* if set, this is a re-used connection */
|
||||||
|
bool chunk; /* if set, this is a chunked transfer-encoding */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -318,9 +330,9 @@ struct connectdata {
|
|||||||
struct HTTP *gopher; /* alias, just for the sake of being more readable */
|
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 HTTP *https; /* alias, just for the sake of being more readable */
|
||||||
struct FTP *ftp;
|
struct FTP *ftp;
|
||||||
#if 0 /* no need for special ones for these: */
|
|
||||||
struct TELNET *telnet;
|
|
||||||
struct FILE *file;
|
struct FILE *file;
|
||||||
|
void *telnet; /* private for telnet.c-eyes only */
|
||||||
|
#if 0 /* no need for special ones for these: */
|
||||||
struct LDAP *ldap;
|
struct LDAP *ldap;
|
||||||
struct DICT *dict;
|
struct DICT *dict;
|
||||||
#endif
|
#endif
|
||||||
|
2
maketgz
2
maketgz
@@ -11,7 +11,7 @@ libversion="$version"
|
|||||||
# Now we have a section to get the major, minor and patch number from the
|
# Now we have a section to get the major, minor and patch number from the
|
||||||
# full version string. We create a single hexadecimal number from it '0xMMmmpp'
|
# full version string. We create a single hexadecimal number from it '0xMMmmpp'
|
||||||
#
|
#
|
||||||
perl='$a=<STDIN>;@p=split("\\.",$a);for(0..2){printf STDOUT ("%02x",$p[0+$_]);}';
|
perl='$a=<STDIN>;@p=split("[\\.-]",$a);for(0..2){printf STDOUT ("%02x",$p[0+$_]);}';
|
||||||
|
|
||||||
numeric=`echo $libversion | perl -e "$perl"`
|
numeric=`echo $libversion | perl -e "$perl"`
|
||||||
|
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
#define CURL_NAME "curl"
|
#define CURL_NAME "curl"
|
||||||
#define CURL_VERSION "7.7-alpha2"
|
#define CURL_VERSION "7.7-beta1"
|
||||||
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
||||||
|
32
tests/README
32
tests/README
@@ -7,7 +7,7 @@
|
|||||||
The cURL Test Suite
|
The cURL Test Suite
|
||||||
|
|
||||||
Requires:
|
Requires:
|
||||||
perl
|
perl (and a unix-style shell)
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
'make test'. This invokes the 'runtests.pl' perl script. Edit the top
|
'make test'. This invokes the 'runtests.pl' perl script. Edit the top
|
||||||
@@ -15,7 +15,8 @@ Run:
|
|||||||
|
|
||||||
The script breaks on the first test that doesn't do OK. Use -a to prevent
|
The script breaks on the first test that doesn't do OK. Use -a to prevent
|
||||||
the script to abort on the first error. Run the script with -v for more
|
the script to abort on the first error. Run the script with -v for more
|
||||||
verbose output.
|
verbose output. Use -d to run the test servers with debug output enabled as
|
||||||
|
well.
|
||||||
|
|
||||||
Use -s fort shorter output, or pass a string with test numbers to run
|
Use -s fort shorter output, or pass a string with test numbers to run
|
||||||
specific tests only (like ./runtests.pl "3 4" to test 3 and 4 only)
|
specific tests only (like ./runtests.pl "3 4" to test 3 and 4 only)
|
||||||
@@ -26,9 +27,24 @@ Memory:
|
|||||||
automatically detect if that is the case, and it will use the ../memanalyze
|
automatically detect if that is the case, and it will use the ../memanalyze
|
||||||
script to analyze the memory debugging output.
|
script to analyze the memory debugging output.
|
||||||
|
|
||||||
|
Debug:
|
||||||
|
If a test case fails, you can conveniently get the script to invoke the
|
||||||
|
debugger (gdb) for you with the server running and the exact same command
|
||||||
|
line parameters that failed. Just invoke 'runtests.pl <test number> -g' and
|
||||||
|
then just type 'run' in the debugger to perform the command through the
|
||||||
|
debugger.
|
||||||
|
|
||||||
|
If a test case causes a core dump, analyze it by running gdb like:
|
||||||
|
|
||||||
|
# gdb ../curl/src core
|
||||||
|
|
||||||
|
... and get a stack trace with the gdb command:
|
||||||
|
|
||||||
|
(gdb) where
|
||||||
|
|
||||||
Logs:
|
Logs:
|
||||||
All logs are generated in the logs/ subdirctory (it is emtpied first
|
All logs are generated in the logs/ subdirctory (it is emtpied first
|
||||||
in the runtests.sh script)
|
in the runtests.pl script)
|
||||||
|
|
||||||
Data:
|
Data:
|
||||||
All test-data are put in the data/ subdirctory.
|
All test-data are put in the data/ subdirctory.
|
||||||
@@ -45,8 +61,10 @@ Data:
|
|||||||
|
|
||||||
replyN.txt: the full dump the server should reply to curl for this test.
|
replyN.txt: the full dump the server should reply to curl for this test.
|
||||||
If the final result that curl should've got is not in this
|
If the final result that curl should've got is not in this
|
||||||
file, you can instead name the file replyN0001.txt. This enables
|
file, you can instead name the file replyN0001.txt. This
|
||||||
you to fiddle more. ;-)
|
enables you to fiddle more. ;-) Alas, the server sends the
|
||||||
|
replyN.txt file but checks the result after the test against
|
||||||
|
the *0001.txt file.
|
||||||
|
|
||||||
stdoutN.txt: if this file is present, curl's stdout is compared against
|
stdoutN.txt: if this file is present, curl's stdout is compared against
|
||||||
this file to see that they're identical. If this is present,
|
this file to see that they're identical. If this is present,
|
||||||
@@ -63,7 +81,7 @@ Data:
|
|||||||
of the ftp server. It uses a simple syntax that is left to
|
of the ftp server. It uses a simple syntax that is left to
|
||||||
describe here!
|
describe here!
|
||||||
|
|
||||||
FIX:
|
TODO:
|
||||||
|
|
||||||
* Make httpserver.pl work when we PUT without Content-Length:
|
* Make httpserver.pl work when we PUT without Content-Length:
|
||||||
|
* Add persistant connection support and test cases
|
||||||
|
@@ -62,4 +62,6 @@ command30.txt name29.txt prot29.txt reply29.txt \
|
|||||||
command31.txt name32.txt reply31.txt reply32.txt \
|
command31.txt name32.txt reply31.txt reply32.txt \
|
||||||
command32.txt prot31.txt reply310001.txt reply320001.txt \
|
command32.txt prot31.txt reply310001.txt reply320001.txt \
|
||||||
name31.txt prot32.txt reply310002.txt reply320002.txt \
|
name31.txt prot32.txt reply310002.txt reply320002.txt \
|
||||||
command33.txt extra33.txt name33.txt prot33.txt reply33.txt
|
command33.txt extra33.txt name33.txt prot33.txt reply33.txt \
|
||||||
|
command34.txt prot34.txt reply340001.txt name34.txt reply34.txt \
|
||||||
|
command35.txt name35.txt prot35.txt reply35.txt
|
||||||
|
1
tests/data/command34.txt
Normal file
1
tests/data/command34.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
http://%HOSTIP:%HOSTPORT/34
|
1
tests/data/command35.txt
Normal file
1
tests/data/command35.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
http://%HOSTIP:%HOSTPORT/want/35 --include --head
|
@@ -1 +1 @@
|
|||||||
HTTP HEAD
|
HTTP HEAD with Connection: close
|
||||||
|
1
tests/data/name34.txt
Normal file
1
tests/data/name34.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
HTTP GET with chunked Transfer-Encoding
|
1
tests/data/name35.txt
Normal file
1
tests/data/name35.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
HTTP HEAD without Connection: close
|
@@ -1,4 +1,4 @@
|
|||||||
GET /1 HTTP/1.0
|
GET /1 HTTP/1.1
|
||||||
User-Agent: curl/7.4.2-pre3 (sparc-sun-solaris2.7) libcurl 7.4.2-pre3 (SSL 0.9.6)
|
User-Agent: curl/7.4.2-pre3 (sparc-sun-solaris2.7) libcurl 7.4.2-pre3 (SSL 0.9.6)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
PUT /we/want/10 HTTP/1.0
|
PUT /we/want/10 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE A
|
TYPE A
|
||||||
LIST
|
LIST
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PORT 127,0,0,1,243,212
|
PORT 127,0,0,1,243,212
|
||||||
TYPE A
|
TYPE A
|
||||||
LIST
|
LIST
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
RETR 102
|
RETR 102
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
CWD a/path
|
CWD a/path
|
||||||
PORT 127,0,0,1,246,33
|
PORT 127,0,0,1,246,33
|
||||||
TYPE I
|
TYPE I
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
CWD a/path
|
CWD a/path
|
||||||
MDTM 103
|
MDTM 103
|
||||||
TYPE I
|
TYPE I
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER userdude
|
USER userdude
|
||||||
PASS passfellow
|
PASS passfellow
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE A
|
TYPE A
|
||||||
RETR 103
|
RETR 103
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
CWD /path with spaces/and things2
|
CWD /path with spaces/and things2
|
||||||
PASV
|
PASV
|
||||||
TYPE A
|
TYPE A
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
STOR 107
|
STOR 107
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
CWD CWD/STOR/RETR
|
CWD CWD/STOR/RETR
|
||||||
PORT 127,0,0,1,5,109
|
PORT 127,0,0,1,5,109
|
||||||
TYPE I
|
TYPE I
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
APPE 109
|
APPE 109
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /want/data/110002.txt?coolsite=yes HTTP/1.0
|
GET /want/data/110002.txt?coolsite=yes HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
SIZE 110
|
SIZE 110
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
APPE 112
|
APPE 112
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /want/12 HTTP/1.0
|
GET /want/12 HTTP/1.1
|
||||||
Range: bytes=100-200
|
Range: bytes=100-200
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
RETR 106
|
RETR 106
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS curl_by_daniel@haxx.se
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
DELE before_transfer
|
DELE before_transfer
|
||||||
PASV
|
PASV
|
||||||
TYPE I
|
TYPE I
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
DELETE /want/13 HTTP/1.0
|
DELETE /want/13 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
HEAD /want/14 HTTP/1.0
|
HEAD /want/14 HTTP/1.1
|
||||||
User-Agent: curl/7.4.2-pre4 (sparc-sun-solaris2.7) libcurl 7.4.2-pre4
|
User-Agent: curl/7.4.2-pre4 (sparc-sun-solaris2.7) libcurl 7.4.2-pre4
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /want/15 HTTP/1.0
|
GET /want/15 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET http://we.want.that.site.com/2 HTTP/1.0
|
GET http://we.want.that.site.com/2 HTTP/1.1
|
||||||
Proxy-authorization: Basic ZmFrZUB1c2VyOqenp2xvb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb28=
|
Proxy-authorization: Basic ZmFrZUB1c2VyOqenp2xvb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb28=
|
||||||
Host: we.want.that.site.com
|
Host: we.want.that.site.com
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
MOOO /that.site.com/17 HTTP/1.0
|
MOOO /that.site.com/17 HTTP/1.1
|
||||||
User-Agent: agent007 license to drill
|
User-Agent: agent007 license to drill
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /11 HTTP/1.0
|
GET /11 HTTP/1.1
|
||||||
User-Agent: curl/7.4.2 (sparc-sun-solaris2.7) libcurl 7.4.2
|
User-Agent: curl/7.4.2 (sparc-sun-solaris2.7) libcurl 7.4.2
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /2 HTTP/1.0
|
GET /2 HTTP/1.1
|
||||||
Authorization: Basic ZmFrZTp1c2Vy
|
Authorization: Basic ZmFrZTp1c2Vy
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
GET /want/25 HTTP/1.0
|
GET /want/25 HTTP/1.1
|
||||||
User-Agent: curl/7.6-pre1 (sparc-sun-solaris2.7) libcurl 7.5.2 (SSL 0.9.6) (krb4 enabled)
|
User-Agent: curl/7.6-pre1 (sparc-sun-solaris2.7) libcurl 7.5.2 (SSL 0.9.6) (krb4 enabled)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /want/22 HTTP/1.0
|
GET /want/22 HTTP/1.1
|
||||||
User-Agent: curl/7.6-pre1 (sparc-sun-solaris2.7) libcurl 7.6-pre1 (SSL 0.9.6) (krb4 enabled)
|
User-Agent: curl/7.6-pre1 (sparc-sun-solaris2.7) libcurl 7.6-pre1 (SSL 0.9.6) (krb4 enabled)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /wantit/{}[]/28 HTTP/1.0
|
GET /wantit/{}[]/28 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /29 HTTP/1.0
|
GET /29 HTTP/1.1
|
||||||
Range: bytes=200-
|
Range: bytes=200-
|
||||||
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
POST /3 HTTP/1.0
|
POST /3 HTTP/1.1
|
||||||
Authorization: Basic ZmFrZTotdXNlcg==
|
Authorization: Basic ZmFrZTotdXNlcg==
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /30 HTTP/1.0
|
GET /30 HTTP/1.1
|
||||||
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
POST /moo/moo/moo/310002 HTTP/1.0
|
POST /moo/moo/moo/310002 HTTP/1.1
|
||||||
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /moo/moo/moo/320002 HTTP/1.0
|
GET /moo/moo/moo/320002 HTTP/1.1
|
||||||
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
PUT /33 HTTP/1.0
|
PUT /33 HTTP/1.1
|
||||||
Content-Range: bytes 50-149/150
|
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)
|
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
|
Host: 127.0.0.1:8999
|
||||||
|
6
tests/data/prot34.txt
Normal file
6
tests/data/prot34.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
GET /34 HTTP/1.1
|
||||||
|
User-Agent: curl/7.7-alpha2 (sparc-sun-solaris2.7) libcurl 7.7-alpha2 (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, */*
|
||||||
|
|
6
tests/data/prot35.txt
Normal file
6
tests/data/prot35.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
HEAD /want/35 HTTP/1.1
|
||||||
|
User-Agent: curl/7.7-alpha2 (sparc-sun-solaris2.7) libcurl 7.7-alpha2 (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, */*
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
GET /4 HTTP/1.0
|
GET /4 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
extra-header: here
|
extra-header: here
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET http://127.0.0.1:8999/we/want/that/page/5 HTTP/1.0
|
GET http://127.0.0.1:8999/we/want/that/page/5 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /we/want/that/page/6 HTTP/1.0
|
GET /we/want/that/page/6 HTTP/1.1
|
||||||
Cookie: name=contents;name2=content2
|
Cookie: name=contents;name2=content2
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /we/want/7 HTTP/1.0
|
GET /we/want/7 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
GET /we/want/8 HTTP/1.0
|
GET /we/want/8 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
POST /we/want/9 HTTP/1.0
|
POST /we/want/9 HTTP/1.1
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
HTTP/1.1 200 OK
|
HTTP/1.1 200 OK
|
||||||
Server: thebest/1.0
|
Server: thebest/1.0
|
||||||
|
Connection: close
|
||||||
|
|
||||||
no?
|
no?
|
||||||
|
13
tests/data/reply34.txt
Normal file
13
tests/data/reply34.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
HTTP/1.1 200 funky chunky!
|
||||||
|
Server: fakeit/1.0
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
Connection: mooo
|
||||||
|
|
||||||
|
40
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
30
|
||||||
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
20;heresatest=moooo
|
||||||
|
ccccccccccccccccccccccccccccccc
|
||||||
|
0
|
||||||
|
muuu
|
8
tests/data/reply340001.txt
Normal file
8
tests/data/reply340001.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
HTTP/1.1 200 funky chunky!
|
||||||
|
Server: fakeit/1.0
|
||||||
|
Transfer-Encoding: chunked
|
||||||
|
Connection: mooo
|
||||||
|
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||||
|
ccccccccccccccccccccccccccccccc
|
4
tests/data/reply35.txt
Normal file
4
tests/data/reply35.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
HTTP/1.1 200 OK
|
||||||
|
Server: thebest/1.0
|
||||||
|
Silly-but-last-header: funny
|
||||||
|
|
@@ -18,5 +18,6 @@ HTTP/1.1 301 This is a weirdo text message
|
|||||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
Server: test-server/fake
|
Server: test-server/fake
|
||||||
Location: data/110002.txt?coolsite=yes
|
Location: data/110002.txt?coolsite=yes
|
||||||
|
Connection: close
|
||||||
|
|
||||||
This server reply is for testing a simple Location: following
|
This server reply is for testing a simple Location: following
|
||||||
|
@@ -350,6 +350,10 @@ for ( $waitedpid = 0;
|
|||||||
&customize(); # read test control instructions
|
&customize(); # read test control instructions
|
||||||
|
|
||||||
print @welcome;
|
print @welcome;
|
||||||
|
if($verbose) {
|
||||||
|
print STDERR "OUT:\n";
|
||||||
|
print STDERR @welcome;
|
||||||
|
}
|
||||||
my $state="fresh";
|
my $state="fresh";
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
|
@@ -154,6 +154,10 @@ sub runftpserver {
|
|||||||
|
|
||||||
if ($RUNNING != 1) {
|
if ($RUNNING != 1) {
|
||||||
my $flag=$debugprotocol?"-v ":"";
|
my $flag=$debugprotocol?"-v ":"";
|
||||||
|
if($debugprotocol) {
|
||||||
|
print "* Starts ftp server verbose:\n";
|
||||||
|
print "perl $srcdir/ftpserver.pl $flag $FTPPORT &\n";
|
||||||
|
}
|
||||||
system("perl $srcdir/ftpserver.pl $flag $FTPPORT &");
|
system("perl $srcdir/ftpserver.pl $flag $FTPPORT &");
|
||||||
sleep 1; # give it a little time to start
|
sleep 1; # give it a little time to start
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user