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
|
||||
|
||||
** 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)
|
||||
- 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 */
|
||||
#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?
|
||||
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 Check for the presence of Kerberos4 libraries and headers
|
||||
dnl **********************************************************************
|
||||
@@ -545,7 +575,8 @@ else
|
||||
dnl these can only exist if openssl exists
|
||||
|
||||
AC_CHECK_FUNCS( RAND_status \
|
||||
RAND_screen )
|
||||
RAND_screen \
|
||||
RAND_egd )
|
||||
|
||||
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.8 How do I tell curl to follow HTTP redirects?
|
||||
3.9 How do I use curl in PHP?
|
||||
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
|
||||
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
|
||||
|
||||
4. Running Problems
|
||||
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
|
||||
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*
|
||||
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?
|
||||
|
||||
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
|
||||
same connection. The only available way to do multiple requests is to
|
||||
init/perform/cleanup for each request.
|
||||
@@ -512,6 +515,9 @@ FAQ
|
||||
|
||||
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
|
||||
for doing multiple file transfers, there's no support for Keep-Alive or
|
||||
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
|
||||
|
||||
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 interface is meant to be very simple for applictions/programmers, hence
|
||||
the name "easy". We have therefore minimized the number of entries.
|
||||
|
||||
The Easy Interface
|
||||
|
||||
When using the easy interface, you init your easy-session and get a handle,
|
||||
which you use as input to the following interface functions you use.
|
||||
When using the easy interface, you init your session and get a handle, which
|
||||
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,
|
||||
most important among them is the URL itself. You might want to set some
|
||||
callbacks as well that will be called from the library when data is available
|
||||
etc.
|
||||
most important among them is the URL itself (you can't transfer anything
|
||||
without a specified URL as you may have figured out yourself). You might want
|
||||
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
|
||||
the entire operation and won't return until it is done or failed.
|
||||
When all is setup, you tell libcurl to perform the transfer using
|
||||
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
|
||||
libcurl is entirely off the hook!
|
||||
After the transfer has been made, you cleanup the session with
|
||||
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()
|
||||
curl_easy_setopt()
|
||||
curl_easy_perform()
|
||||
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:
|
||||
While the above mentioned four functions are the main functions to use in the
|
||||
easy interface, there is a series of other helpful functions to use. They
|
||||
are:
|
||||
|
||||
curl_version() - displays the libcurl version
|
||||
curl_getdate() - converts a date string to time_t
|
||||
curl_getenv() - portable environment variable reader
|
||||
curl_easy_getinfo() - get information about a performed transfer
|
||||
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_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
|
||||
|
||||
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
|
||||
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
|
||||
few teasers...)
|
||||
To do for the 7.7 release:
|
||||
|
||||
* Fix the random seeding. Add --egd-socket and --random-file options to the
|
||||
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
|
||||
host is requested.
|
||||
|
||||
* Make the curl tool support URLs that start with @ that would then mean that
|
||||
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
|
||||
support @http://whatever.com that would first load a list and then get the
|
||||
URLs mentioned in the list. I figure -O or something would have to be
|
||||
implied by such an action.
|
||||
To do in a future release:
|
||||
|
||||
* Extend the test suite to include telnet and https. The telnet could just do
|
||||
ftp or http operations (for which we have test servers) and the https would
|
||||
probably work against/with some of the openssl tools.
|
||||
|
||||
* 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
|
||||
@@ -31,16 +37,11 @@ For the future
|
||||
an alternative to OpenSSL:
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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: NTLM. Support for that MS crap called NTLM
|
||||
authentication. MS proxies and servers sometime require that. Since that
|
||||
protocol is a proprietary one, it involves reverse engineering and network
|
||||
sniffing. This should however be a library-based functionality. There are a
|
||||
@@ -70,30 +70,19 @@ For the future
|
||||
http://hopf.math.nwu.edu/testpage/digest/
|
||||
And some friendly person's server source code is available at
|
||||
http://hopf.math.nwu.edu/digestauth/index.html
|
||||
|
||||
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
|
||||
a lot better authentication method than the more common "Basic". Basic
|
||||
sends the password in cleartext over the network, this "Digest" method uses
|
||||
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
|
||||
Ftp-kind proxy, Socks5, whatever kind of proxies are there?
|
||||
|
||||
* IPv6 Awareness and support
|
||||
Where ever it would fit. configure search for v6-versions of a few
|
||||
functions and then use them instead is of course the first thing to do...
|
||||
RFC 2428 "FTP Extensions for IPv6 and NATs" will be interesting. PORT
|
||||
should be replaced with EPRT for IPv6, and EPSV instead of PASV.
|
||||
* IPv6 Awareness and support. (This is partly done.) RFC 2428 "FTP
|
||||
Extensions for IPv6 and NATs" is interesting. PORT should be replaced with
|
||||
EPRT for IPv6 (done), and EPSV instead of PASV. HTTP proxies are left to
|
||||
add support for.
|
||||
|
||||
* SSL for more protocols, like SSL-FTP...
|
||||
(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]
|
||||
.\" 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
|
||||
curl_easy_cleanup - End a libcurl "easy" session
|
||||
curl_easy_cleanup - End a libcurl session
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/easy.h>
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "curl_easy_cleanup(CURL *" handle ");
|
||||
.BI "curl_easy_cleanup(CURL *" handle ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
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
|
||||
.I handle
|
||||
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
|
||||
None
|
||||
.SH "SEE ALSO"
|
||||
|
@@ -2,11 +2,11 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/easy.h>
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"
|
||||
.ad
|
||||
@@ -83,8 +83,8 @@ verification that was requested (using the CURLOPT_SSL_VERIFYPEER option to
|
||||
curl_easy_setopt). (Added in 7.4.2)
|
||||
.TP
|
||||
.B CURLINFO_CONTENT_LENGTH_DOWNLOAD
|
||||
Pass a pointer to a double to receive the content-length of the download.
|
||||
(Added in 7.6.1)
|
||||
Pass a pointer to a double to receive the content-length of the download. This
|
||||
is the value read from the Content-Length: field. (Added in 7.6.1)
|
||||
.TP
|
||||
.B CURLINFO_CONTENT_LENGTH_UPLOAD
|
||||
Pass a pointer to a double to receive the specified size of the upload.
|
||||
|
@@ -2,11 +2,11 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_easy_init - Start a libcurl "easy" session
|
||||
curl_easy_init - Start a libcurl session
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/easy.h>
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURL *curl_easy_init( );"
|
||||
.ad
|
||||
@@ -19,6 +19,10 @@ when the operation is complete.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
If this function returns NULL, something went wrong and you cannot use the
|
||||
other curl functions.
|
||||
|
@@ -2,11 +2,11 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_easy_perform - Do the actual transfer in a "easy" session
|
||||
curl_easy_perform - Perform a file transfer
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/easy.h>
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_easy_perform(CURL *" handle ");
|
||||
.ad
|
||||
@@ -17,9 +17,22 @@ It must be called with the same
|
||||
.I handle
|
||||
as input as the curl_easy_init call returned.
|
||||
|
||||
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.
|
||||
libcurl version 7.7 or later (for older versions see below): You can do any
|
||||
amount of calls to curl_easy_perform() while using the same handle. If you
|
||||
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
|
||||
0 means everything was ok, non-zero means an error occurred as
|
||||
.I <curl/curl.h>
|
||||
|
@@ -2,11 +2,11 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_easy_setopt - Set curl easy-session options
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/easy.h>
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);
|
||||
.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
|
||||
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
|
||||
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
|
||||
.I "handle"
|
||||
@@ -86,14 +90,16 @@ libcurl what the expected size of the infile is.
|
||||
.TP
|
||||
.B CURLOPT_URL
|
||||
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
|
||||
.B CURLOPT_PROXY
|
||||
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
|
||||
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
|
||||
"[protocol]://" since any such prefix will be ignored.
|
||||
[protocol]:// since any such prefix will be ignored.
|
||||
.TP
|
||||
.B CURLOPT_PROXYPORT
|
||||
Set this long with this option to set the proxy port to use unless it is
|
||||
@@ -189,9 +195,11 @@ prompted for it.
|
||||
.TP
|
||||
.B CURLOPT_RANGE
|
||||
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
|
||||
.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
|
||||
.B CURLOPT_ERRORBUFFER
|
||||
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
|
||||
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
|
||||
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
|
||||
.B CURLOPT_POSTFIELDS
|
||||
Pass a char * as parameter, which should be the full data to post in a HTTP
|
||||
|
@@ -2,7 +2,7 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_formfree - free a previously build multipart/formdata HTTP POST chain
|
||||
.SH SYNOPSIS
|
||||
|
@@ -2,7 +2,7 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_formparse - add a section to a multipart/formdata HTTP POST
|
||||
.SH SYNOPSIS
|
||||
|
@@ -2,7 +2,7 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_getdate - Convert an date in a ASCII string to number of seconds since
|
||||
January 1, 1970
|
||||
|
@@ -2,7 +2,7 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_getenv - return value for environment name
|
||||
.SH SYNOPSIS
|
||||
|
@@ -2,7 +2,7 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_slist_append - add a string to an slist
|
||||
.SH SYNOPSIS
|
||||
|
@@ -2,13 +2,13 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_slist_free_all - free an entire curl_slist list
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "void curl_slist_free_all(struct curl_slit *" list);
|
||||
.BI "void curl_slist_free_all(struct curl_slist *" list);
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
curl_slist_free_all() removes all traces of a previously built curl_slist
|
||||
|
@@ -2,11 +2,11 @@
|
||||
.\" nroff -man [file]
|
||||
.\" 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
|
||||
curl_version - returns the libcurl version string
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/easy.h>
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "char *curl_version( );"
|
||||
.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
|
||||
its important components (like OpenSSL version).
|
||||
|
||||
Do note that this returns the actual running lib's version, you might have
|
||||
installed a newer lib's include files in your system which may turn your
|
||||
LIBCURL_VERSION #define value to differ from this result.
|
||||
Note: this returns the actual running lib's version, you might have installed
|
||||
a newer lib's include files in your system which may turn your LIBCURL_VERSION
|
||||
#define value to differ from this result.
|
||||
.SH RETURN VALUE
|
||||
A pointer to a zero terminated string.
|
||||
.SH "SEE ALSO"
|
||||
|
@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
EXTRA_DIST =
|
||||
README curlgtk.c sepheaders.c simple.c postit.c \
|
||||
win32sockets.c \
|
||||
win32sockets.c persistant.c \
|
||||
getpageinvar.php simpleget.php simplepost.php
|
||||
|
||||
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 {
|
||||
CURLE_OK = 0,
|
||||
CURLE_UNSUPPORTED_PROTOCOL,
|
||||
CURLE_FAILED_INIT,
|
||||
CURLE_URL_MALFORMAT,
|
||||
CURLE_URL_MALFORMAT_USER,
|
||||
CURLE_COULDNT_RESOLVE_PROXY,
|
||||
CURLE_COULDNT_RESOLVE_HOST,
|
||||
CURLE_COULDNT_CONNECT,
|
||||
CURLE_FTP_WEIRD_SERVER_REPLY,
|
||||
CURLE_FTP_ACCESS_DENIED,
|
||||
CURLE_FTP_USER_PASSWORD_INCORRECT,
|
||||
CURLE_FTP_WEIRD_PASS_REPLY,
|
||||
CURLE_FTP_WEIRD_USER_REPLY,
|
||||
CURLE_FTP_WEIRD_PASV_REPLY,
|
||||
CURLE_FTP_WEIRD_227_FORMAT,
|
||||
CURLE_FTP_CANT_GET_HOST,
|
||||
CURLE_FTP_CANT_RECONNECT,
|
||||
CURLE_FTP_COULDNT_SET_BINARY,
|
||||
CURLE_PARTIAL_FILE,
|
||||
CURLE_FTP_COULDNT_RETR_FILE,
|
||||
CURLE_FTP_WRITE_ERROR,
|
||||
CURLE_FTP_QUOTE_ERROR,
|
||||
CURLE_HTTP_NOT_FOUND,
|
||||
CURLE_WRITE_ERROR,
|
||||
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
|
||||
CURLE_FAILED_INIT, /* 2 */
|
||||
CURLE_URL_MALFORMAT, /* 3 */
|
||||
CURLE_URL_MALFORMAT_USER, /* 4 */
|
||||
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
|
||||
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
|
||||
CURLE_COULDNT_CONNECT, /* 7 */
|
||||
CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
|
||||
CURLE_FTP_ACCESS_DENIED, /* 9 */
|
||||
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */
|
||||
CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
|
||||
CURLE_FTP_WEIRD_USER_REPLY, /* 12 */
|
||||
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
|
||||
CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
|
||||
CURLE_FTP_CANT_GET_HOST, /* 15 */
|
||||
CURLE_FTP_CANT_RECONNECT, /* 16 */
|
||||
CURLE_FTP_COULDNT_SET_BINARY, /* 17 */
|
||||
CURLE_PARTIAL_FILE, /* 18 */
|
||||
CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
|
||||
CURLE_FTP_WRITE_ERROR, /* 20 */
|
||||
CURLE_FTP_QUOTE_ERROR, /* 21 */
|
||||
CURLE_HTTP_NOT_FOUND, /* 22 */
|
||||
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 */
|
||||
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
|
||||
CURL_LAST /* never use! */
|
||||
} CURLcode;
|
||||
|
||||
/* This is just to make older programs not break: */
|
||||
@@ -458,8 +444,8 @@ char *curl_getenv(char *variable);
|
||||
char *curl_version(void);
|
||||
|
||||
/* This is the version number */
|
||||
#define LIBCURL_VERSION "7.7-alpha2"
|
||||
#define LIBCURL_VERSION_NUM 0x070000
|
||||
#define LIBCURL_VERSION "7.7-beta1"
|
||||
#define LIBCURL_VERSION_NUM 0x070700
|
||||
|
||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||
struct curl_slist {
|
||||
|
@@ -58,7 +58,8 @@ getenv.c ldap.h ssluse.h \
|
||||
escape.c mprintf.c telnet.c \
|
||||
escape.h getpass.c netrc.c telnet.h \
|
||||
getinfo.c transfer.c strequal.c strequal.h easy.c \
|
||||
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h
|
||||
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
|
||||
|
||||
|
58
lib/file.c
58
lib/file.c
@@ -91,25 +91,19 @@
|
||||
#include "memdebug.h"
|
||||
#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
|
||||
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;
|
||||
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;
|
||||
char *actual_path = curl_unescape(conn->path, 0);
|
||||
struct FILE *file;
|
||||
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__)
|
||||
int i;
|
||||
@@ -126,9 +120,37 @@ CURLcode file(struct connectdata *conn)
|
||||
free(actual_path);
|
||||
|
||||
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;
|
||||
}
|
||||
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)) {
|
||||
/* we could stat it, then read out the size */
|
||||
expected_size = statbuf.st_size;
|
||||
|
@@ -23,6 +23,6 @@
|
||||
*
|
||||
* $Id$
|
||||
*****************************************************************************/
|
||||
CURLcode file(struct connectdata *conn);
|
||||
|
||||
CURLcode Curl_file(struct connectdata *conn);
|
||||
CURLcode Curl_file_connect(struct connectdata *conn);
|
||||
#endif
|
||||
|
@@ -296,6 +296,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
||||
memset(ftp, 0, sizeof(struct FTP));
|
||||
conn->proto.ftp = ftp;
|
||||
|
||||
/* We always support persistant connections on ftp */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
/* get some initial data into the ftp struct */
|
||||
ftp->bytecountp = &conn->bytecount;
|
||||
|
||||
|
@@ -104,6 +104,7 @@
|
||||
#include "memdebug.h"
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
* 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
|
||||
@@ -205,7 +206,7 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
|
||||
}
|
||||
|
||||
/* end of the add_buffer functions */
|
||||
/*****************************************************************************/
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Read everything until a newline.
|
||||
@@ -309,6 +310,9 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTP stuff to do at connect-time.
|
||||
*/
|
||||
CURLcode Curl_http_connect(struct connectdata *conn)
|
||||
{
|
||||
struct UrlData *data;
|
||||
@@ -402,6 +406,9 @@ CURLcode Curl_http(struct connectdata *conn)
|
||||
else
|
||||
http = conn->proto.http;
|
||||
|
||||
/* We default to persistant connections */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
|
||||
data->bits.upload) {
|
||||
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_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
|
||||
|
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 */
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
#include <openssl/rand.h>
|
||||
|
||||
static char global_passwd[64];
|
||||
|
||||
@@ -58,16 +59,93 @@ static int passwd_callback(char *buf, int num, int verify
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function is *highly* inspired by (and parts are directly stolen
|
||||
* from) source from the SSLeay package written by Eric Young
|
||||
* (eay@cryptsoft.com). */
|
||||
static
|
||||
bool seed_enough(struct connectdata *conn, /* unused for now */
|
||||
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
|
||||
int cert_stuff(struct UrlData *data,
|
||||
struct connectdata *conn,
|
||||
int random_the_seed(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 *key_file)
|
||||
{
|
||||
struct UrlData *data = conn->data;
|
||||
if (cert_file != NULL) {
|
||||
SSL *ssl;
|
||||
X509 *x509;
|
||||
@@ -123,9 +201,6 @@ int cert_stuff(struct UrlData *data,
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
static
|
||||
int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
@@ -156,28 +231,8 @@ Curl_SSLConnect(struct connectdata *conn)
|
||||
/* Lets get nice error messages */
|
||||
SSL_load_error_strings();
|
||||
|
||||
#ifdef HAVE_RAND_STATUS
|
||||
/* RAND_status() was introduced in OpenSSL 0.9.5 */
|
||||
if(0 == RAND_status())
|
||||
#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
|
||||
}
|
||||
/* Make funny stuff to get random input */
|
||||
random_the_seed(conn);
|
||||
|
||||
/* Setup all the global SSL stuff */
|
||||
SSLeay_add_ssl_algorithms();
|
||||
@@ -202,7 +257,7 @@ Curl_SSLConnect(struct connectdata *conn)
|
||||
}
|
||||
|
||||
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");
|
||||
return 2;
|
||||
}
|
||||
|
370
lib/telnet.c
370
lib/telnet.c
@@ -84,16 +84,16 @@
|
||||
|
||||
#define SUBBUFSIZE 512
|
||||
|
||||
#define SB_CLEAR() subpointer = subbuffer;
|
||||
#define SB_TERM() { subend = subpointer; SB_CLEAR(); }
|
||||
#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
|
||||
*subpointer++ = (c); \
|
||||
#define SB_CLEAR(x) x->subpointer = x->subbuffer;
|
||||
#define SB_TERM(x) { x->subend = x->subpointer; SB_CLEAR(x); }
|
||||
#define SB_ACCUM(x,c) if (x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \
|
||||
*x->subpointer++ = (c); \
|
||||
}
|
||||
|
||||
#define SB_GET() ((*subpointer++)&0xff)
|
||||
#define SB_PEEK() ((*subpointer)&0xff)
|
||||
#define SB_EOF() (subpointer >= subend)
|
||||
#define SB_LEN() (subend - subpointer)
|
||||
#define SB_GET(x) ((*x->subpointer++)&0xff)
|
||||
#define SB_PEEK(x) ((*x->subpointer)&0xff)
|
||||
#define SB_EOF(x) (x->subpointer >= x->subend)
|
||||
#define SB_LEN(x) (x->subend - x->subpointer)
|
||||
|
||||
static
|
||||
void telrcv(struct connectdata *,
|
||||
@@ -113,14 +113,19 @@ static void printsub(struct UrlData *data,
|
||||
int direction, unsigned char *pointer, int length);
|
||||
static void suboption(struct connectdata *);
|
||||
|
||||
/* suboptions */
|
||||
static char subbuffer[SUBBUFSIZE];
|
||||
static char *subpointer, *subend; /* buffer for sub-options */
|
||||
/* For negotiation compliant to RFC 1143 */
|
||||
#define NO 0
|
||||
#define YES 1
|
||||
#define WANTYES 2
|
||||
#define WANTNO 3
|
||||
|
||||
#define EMPTY 0
|
||||
#define OPPOSITE 1
|
||||
|
||||
/*
|
||||
* Telnet receiver states for fsm
|
||||
*/
|
||||
static enum
|
||||
typedef enum
|
||||
{
|
||||
TS_DATA = 0,
|
||||
TS_IAC,
|
||||
@@ -131,63 +136,76 @@ static enum
|
||||
TS_CR,
|
||||
TS_SB, /* sub-option collection */
|
||||
TS_SE /* looking for sub-option end */
|
||||
} telrcv_state;
|
||||
} TelnetReceive;
|
||||
|
||||
/* For negotiation compliant to RFC 1143 */
|
||||
#define NO 0
|
||||
#define YES 1
|
||||
#define WANTYES 2
|
||||
#define WANTNO 3
|
||||
struct TELNET {
|
||||
int please_negotiate;
|
||||
int already_negotiated;
|
||||
int us[256];
|
||||
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
|
||||
#define OPPOSITE 1
|
||||
/* suboptions */
|
||||
char subbuffer[SUBBUFSIZE];
|
||||
char *subpointer, *subend; /* buffer for sub-options */
|
||||
|
||||
static int please_negotiate = 0;
|
||||
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 */
|
||||
TelnetReceive telrcv_state;
|
||||
};
|
||||
|
||||
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 */
|
||||
SB_CLEAR();
|
||||
SB_CLEAR(tn);
|
||||
|
||||
/* Set all options to NO */
|
||||
memset(us, NO, 256);
|
||||
memset(usq, NO, 256);
|
||||
memset(us_preferred, NO, 256);
|
||||
memset(him, NO, 256);
|
||||
memset(himq, NO, 256);
|
||||
memset(him_preferred, NO, 256);
|
||||
|
||||
#if 0
|
||||
/* NO is zero => default fill pattern */
|
||||
memset(tn->us, NO, 256);
|
||||
memset(tn->usq, NO, 256);
|
||||
memset(tn->us_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 */
|
||||
us_preferred[TELOPT_BINARY] = YES;
|
||||
us_preferred[TELOPT_SGA] = YES;
|
||||
him_preferred[TELOPT_BINARY] = YES;
|
||||
him_preferred[TELOPT_SGA] = YES;
|
||||
tn->us_preferred[TELOPT_BINARY] = YES;
|
||||
tn->us_preferred[TELOPT_SGA] = YES;
|
||||
tn->him_preferred[TELOPT_BINARY] = YES;
|
||||
tn->him_preferred[TELOPT_SGA] = YES;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static void negotiate(struct connectdata *conn)
|
||||
{
|
||||
int i;
|
||||
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||
|
||||
for(i = 0;i < NTELOPTS;i++)
|
||||
{
|
||||
if(us_preferred[i] == YES)
|
||||
if(tn->us_preferred[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);
|
||||
}
|
||||
}
|
||||
@@ -247,12 +265,13 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
|
||||
static
|
||||
void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||
if(newstate == YES)
|
||||
{
|
||||
switch(him[option])
|
||||
switch(tn->him[option])
|
||||
{
|
||||
case NO:
|
||||
him[option] = WANTYES;
|
||||
tn->him[option] = WANTYES;
|
||||
send_negotiation(conn, DO, option);
|
||||
break;
|
||||
|
||||
@@ -261,11 +280,11 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Already negotiating for YES, queue the request */
|
||||
himq[option] = OPPOSITE;
|
||||
tn->himq[option] = OPPOSITE;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
/* Error: already queued an enable request */
|
||||
@@ -274,13 +293,13 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Error: already negotiating for enable */
|
||||
break;
|
||||
case OPPOSITE:
|
||||
himq[option] = EMPTY;
|
||||
tn->himq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -288,34 +307,34 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
}
|
||||
else /* NO */
|
||||
{
|
||||
switch(him[option])
|
||||
switch(tn->him[option])
|
||||
{
|
||||
case NO:
|
||||
/* Already disabled */
|
||||
break;
|
||||
|
||||
case YES:
|
||||
him[option] = WANTNO;
|
||||
tn->him[option] = WANTNO;
|
||||
send_negotiation(conn, DONT, option);
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Already negotiating for NO */
|
||||
break;
|
||||
case OPPOSITE:
|
||||
himq[option] = EMPTY;
|
||||
tn->himq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
himq[option] = OPPOSITE;
|
||||
tn->himq[option] = OPPOSITE;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
break;
|
||||
@@ -328,12 +347,13 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
|
||||
static
|
||||
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:
|
||||
if(him_preferred[option] == YES)
|
||||
if(tn->him_preferred[option] == YES)
|
||||
{
|
||||
him[option] = YES;
|
||||
tn->him[option] = YES;
|
||||
send_negotiation(conn, DO, option);
|
||||
}
|
||||
else
|
||||
@@ -347,29 +367,29 @@ void rec_will(struct connectdata *conn, int option)
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Error: DONT answered by WILL */
|
||||
him[option] = NO;
|
||||
tn->him[option] = NO;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
/* Error: DONT answered by WILL */
|
||||
him[option] = YES;
|
||||
himq[option] = EMPTY;
|
||||
tn->him[option] = YES;
|
||||
tn->himq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
him[option] = YES;
|
||||
tn->him[option] = YES;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
him[option] = WANTNO;
|
||||
himq[option] = EMPTY;
|
||||
tn->him[option] = WANTNO;
|
||||
tn->himq[option] = EMPTY;
|
||||
send_negotiation(conn, DONT, option);
|
||||
break;
|
||||
}
|
||||
@@ -380,41 +400,42 @@ void rec_will(struct connectdata *conn, int option)
|
||||
static
|
||||
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:
|
||||
/* Already disabled */
|
||||
break;
|
||||
|
||||
case YES:
|
||||
him[option] = NO;
|
||||
tn->him[option] = NO;
|
||||
send_negotiation(conn, DONT, option);
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
him[option] = NO;
|
||||
tn->him[option] = NO;
|
||||
break;
|
||||
|
||||
case OPPOSITE:
|
||||
him[option] = WANTYES;
|
||||
himq[option] = EMPTY;
|
||||
tn->him[option] = WANTYES;
|
||||
tn->himq[option] = EMPTY;
|
||||
send_negotiation(conn, DO, option);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(himq[option])
|
||||
switch(tn->himq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
him[option] = NO;
|
||||
tn->him[option] = NO;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
him[option] = NO;
|
||||
himq[option] = EMPTY;
|
||||
tn->him[option] = NO;
|
||||
tn->himq[option] = EMPTY;
|
||||
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)
|
||||
{
|
||||
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||
if(newstate == YES)
|
||||
{
|
||||
switch(us[option])
|
||||
switch(tn->us[option])
|
||||
{
|
||||
case NO:
|
||||
us[option] = WANTYES;
|
||||
tn->us[option] = WANTYES;
|
||||
send_negotiation(conn, WILL, option);
|
||||
break;
|
||||
|
||||
@@ -437,11 +459,11 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Already negotiating for YES, queue the request */
|
||||
usq[option] = OPPOSITE;
|
||||
tn->usq[option] = OPPOSITE;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
/* Error: already queued an enable request */
|
||||
@@ -450,13 +472,13 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Error: already negotiating for enable */
|
||||
break;
|
||||
case OPPOSITE:
|
||||
usq[option] = EMPTY;
|
||||
tn->usq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -464,34 +486,34 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
||||
}
|
||||
else /* NO */
|
||||
{
|
||||
switch(us[option])
|
||||
switch(tn->us[option])
|
||||
{
|
||||
case NO:
|
||||
/* Already disabled */
|
||||
break;
|
||||
|
||||
case YES:
|
||||
us[option] = WANTNO;
|
||||
tn->us[option] = WANTNO;
|
||||
send_negotiation(conn, WONT, option);
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Already negotiating for NO */
|
||||
break;
|
||||
case OPPOSITE:
|
||||
usq[option] = EMPTY;
|
||||
tn->usq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
usq[option] = OPPOSITE;
|
||||
tn->usq[option] = OPPOSITE;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
break;
|
||||
@@ -504,12 +526,13 @@ void set_local_option(struct connectdata *conn, int option, int newstate)
|
||||
static
|
||||
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:
|
||||
if(us_preferred[option] == YES)
|
||||
if(tn->us_preferred[option] == YES)
|
||||
{
|
||||
us[option] = YES;
|
||||
tn->us[option] = YES;
|
||||
send_negotiation(conn, WILL, option);
|
||||
}
|
||||
else
|
||||
@@ -523,29 +546,29 @@ void rec_do(struct connectdata *conn, int option)
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
/* Error: DONT answered by WILL */
|
||||
us[option] = NO;
|
||||
tn->us[option] = NO;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
/* Error: DONT answered by WILL */
|
||||
us[option] = YES;
|
||||
usq[option] = EMPTY;
|
||||
tn->us[option] = YES;
|
||||
tn->usq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
us[option] = YES;
|
||||
tn->us[option] = YES;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
us[option] = WANTNO;
|
||||
himq[option] = EMPTY;
|
||||
tn->us[option] = WANTNO;
|
||||
tn->himq[option] = EMPTY;
|
||||
send_negotiation(conn, WONT, option);
|
||||
break;
|
||||
}
|
||||
@@ -556,41 +579,42 @@ void rec_do(struct connectdata *conn, int option)
|
||||
static
|
||||
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:
|
||||
/* Already disabled */
|
||||
break;
|
||||
|
||||
case YES:
|
||||
us[option] = NO;
|
||||
tn->us[option] = NO;
|
||||
send_negotiation(conn, WONT, option);
|
||||
break;
|
||||
|
||||
case WANTNO:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
us[option] = NO;
|
||||
tn->us[option] = NO;
|
||||
break;
|
||||
|
||||
case OPPOSITE:
|
||||
us[option] = WANTYES;
|
||||
usq[option] = EMPTY;
|
||||
tn->us[option] = WANTYES;
|
||||
tn->usq[option] = EMPTY;
|
||||
send_negotiation(conn, WILL, option);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WANTYES:
|
||||
switch(usq[option])
|
||||
switch(tn->usq[option])
|
||||
{
|
||||
case EMPTY:
|
||||
us[option] = NO;
|
||||
tn->us[option] = NO;
|
||||
break;
|
||||
case OPPOSITE:
|
||||
us[option] = NO;
|
||||
usq[option] = EMPTY;
|
||||
tn->us[option] = NO;
|
||||
tn->usq[option] = EMPTY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -717,6 +741,7 @@ static int check_telnet_options(struct connectdata *conn)
|
||||
char option_arg[256];
|
||||
char *buf;
|
||||
struct UrlData *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||
|
||||
/* Add the user name as an environment variable if it
|
||||
was given on the command line */
|
||||
@@ -724,9 +749,9 @@ static int check_telnet_options(struct connectdata *conn)
|
||||
{
|
||||
char *buf = malloc(256);
|
||||
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) {
|
||||
@@ -735,15 +760,15 @@ static int check_telnet_options(struct connectdata *conn)
|
||||
|
||||
/* Terminal type */
|
||||
if(strequal(option_keyword, "TTYPE")) {
|
||||
subopt_ttype = option_arg;
|
||||
us_preferred[TELOPT_TTYPE] = YES;
|
||||
tn->subopt_ttype = option_arg;
|
||||
tn->us_preferred[TELOPT_TTYPE] = YES;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Display variable */
|
||||
if(strequal(option_keyword, "XDISPLOC")) {
|
||||
subopt_xdisploc = option_arg;
|
||||
us_preferred[TELOPT_XDISPLOC] = YES;
|
||||
tn->subopt_xdisploc = option_arg;
|
||||
tn->us_preferred[TELOPT_XDISPLOC] = YES;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -752,8 +777,8 @@ static int check_telnet_options(struct connectdata *conn)
|
||||
buf = strdup(option_arg);
|
||||
if(!buf)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
telnet_vars = curl_slist_append(telnet_vars, buf);
|
||||
us_preferred[TELOPT_NEW_ENVIRON] = YES;
|
||||
tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
|
||||
tn->us_preferred[TELOPT_NEW_ENVIRON] = YES;
|
||||
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
|
||||
* side.
|
||||
* No suboptions are supported yet.
|
||||
*/
|
||||
|
||||
static void suboption(struct connectdata *conn)
|
||||
@@ -786,22 +810,23 @@ static void suboption(struct connectdata *conn)
|
||||
char varname[128];
|
||||
char varval[128];
|
||||
struct UrlData *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||
|
||||
printsub(data, '<', (unsigned char *)subbuffer, SB_LEN()+2);
|
||||
switch (subchar = SB_GET()) {
|
||||
printsub(data, '<', (unsigned char *)tn->subbuffer, SB_LEN(tn)+2);
|
||||
switch (subchar = SB_GET(tn)) {
|
||||
case TELOPT_TTYPE:
|
||||
len = strlen(subopt_ttype) + 4 + 2;
|
||||
len = strlen(tn->subopt_ttype) + 4 + 2;
|
||||
snprintf((char *)temp, sizeof(temp),
|
||||
"%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);
|
||||
printsub(data, '>', &temp[2], len-2);
|
||||
break;
|
||||
case TELOPT_XDISPLOC:
|
||||
len = strlen(subopt_xdisploc) + 4 + 2;
|
||||
len = strlen(tn->subopt_xdisploc) + 4 + 2;
|
||||
snprintf((char *)temp, sizeof(temp),
|
||||
"%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);
|
||||
printsub(data, '>', &temp[2], len-2);
|
||||
break;
|
||||
@@ -810,7 +835,7 @@ static void suboption(struct connectdata *conn)
|
||||
"%c%c%c%c", IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS);
|
||||
len = 4;
|
||||
|
||||
for(v = telnet_vars;v;v = v->next) {
|
||||
for(v = tn->telnet_vars;v;v = v->next) {
|
||||
tmplen = (strlen(v->data) + 1);
|
||||
/* Add the variable only if it fits */
|
||||
if(len + tmplen < sizeof(temp)-6) {
|
||||
@@ -839,15 +864,16 @@ void telrcv(struct connectdata *conn,
|
||||
unsigned char c;
|
||||
int index = 0;
|
||||
struct UrlData *data = conn->data;
|
||||
struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
|
||||
|
||||
while(count--)
|
||||
{
|
||||
c = inbuf[index++];
|
||||
|
||||
switch (telrcv_state)
|
||||
switch (tn->telrcv_state)
|
||||
{
|
||||
case TS_CR:
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
if (c == '\0')
|
||||
{
|
||||
break; /* Ignore \0 after CR */
|
||||
@@ -859,12 +885,12 @@ void telrcv(struct connectdata *conn,
|
||||
case TS_DATA:
|
||||
if (c == IAC)
|
||||
{
|
||||
telrcv_state = TS_IAC;
|
||||
tn->telrcv_state = TS_IAC;
|
||||
break;
|
||||
}
|
||||
else if(c == '\r')
|
||||
{
|
||||
telrcv_state = TS_CR;
|
||||
tn->telrcv_state = TS_CR;
|
||||
}
|
||||
|
||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
|
||||
@@ -875,20 +901,20 @@ void telrcv(struct connectdata *conn,
|
||||
switch (c)
|
||||
{
|
||||
case WILL:
|
||||
telrcv_state = TS_WILL;
|
||||
tn->telrcv_state = TS_WILL;
|
||||
continue;
|
||||
case WONT:
|
||||
telrcv_state = TS_WONT;
|
||||
tn->telrcv_state = TS_WONT;
|
||||
continue;
|
||||
case DO:
|
||||
telrcv_state = TS_DO;
|
||||
tn->telrcv_state = TS_DO;
|
||||
continue;
|
||||
case DONT:
|
||||
telrcv_state = TS_DONT;
|
||||
tn->telrcv_state = TS_DONT;
|
||||
continue;
|
||||
case SB:
|
||||
SB_CLEAR();
|
||||
telrcv_state = TS_SB;
|
||||
SB_CLEAR(tn);
|
||||
tn->telrcv_state = TS_SB;
|
||||
continue;
|
||||
case IAC:
|
||||
Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
|
||||
@@ -900,45 +926,45 @@ void telrcv(struct connectdata *conn,
|
||||
printoption(data, "RCVD", IAC, c);
|
||||
break;
|
||||
}
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
continue;
|
||||
|
||||
case TS_WILL:
|
||||
printoption(data, "RCVD", WILL, c);
|
||||
please_negotiate = 1;
|
||||
tn->please_negotiate = 1;
|
||||
rec_will(conn, c);
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
continue;
|
||||
|
||||
case TS_WONT:
|
||||
printoption(data, "RCVD", WONT, c);
|
||||
please_negotiate = 1;
|
||||
tn->please_negotiate = 1;
|
||||
rec_wont(conn, c);
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
continue;
|
||||
|
||||
case TS_DO:
|
||||
printoption(data, "RCVD", DO, c);
|
||||
please_negotiate = 1;
|
||||
tn->please_negotiate = 1;
|
||||
rec_do(conn, c);
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
continue;
|
||||
|
||||
case TS_DONT:
|
||||
printoption(data, "RCVD", DONT, c);
|
||||
please_negotiate = 1;
|
||||
tn->please_negotiate = 1;
|
||||
rec_dont(conn, c);
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
continue;
|
||||
|
||||
case TS_SB:
|
||||
if (c == IAC)
|
||||
{
|
||||
telrcv_state = TS_SE;
|
||||
tn->telrcv_state = TS_SE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SB_ACCUM(c);
|
||||
SB_ACCUM(tn,c);
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -959,27 +985,27 @@ void telrcv(struct connectdata *conn,
|
||||
* we terminate the suboption, and process the
|
||||
* partial suboption if we can.
|
||||
*/
|
||||
SB_ACCUM((unsigned char)IAC);
|
||||
SB_ACCUM(c);
|
||||
subpointer -= 2;
|
||||
SB_TERM();
|
||||
SB_ACCUM(tn, (unsigned char)IAC);
|
||||
SB_ACCUM(tn, c);
|
||||
tn->subpointer -= 2;
|
||||
SB_TERM(tn);
|
||||
|
||||
printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
|
||||
suboption(conn); /* handle sub-option */
|
||||
telrcv_state = TS_IAC;
|
||||
tn->telrcv_state = TS_IAC;
|
||||
goto process_iac;
|
||||
}
|
||||
SB_ACCUM(c);
|
||||
telrcv_state = TS_SB;
|
||||
SB_ACCUM(tn,c);
|
||||
tn->telrcv_state = TS_SB;
|
||||
}
|
||||
else
|
||||
{
|
||||
SB_ACCUM((unsigned char)IAC);
|
||||
SB_ACCUM((unsigned char)SE);
|
||||
subpointer -= 2;
|
||||
SB_TERM();
|
||||
SB_ACCUM(tn, (unsigned char)IAC);
|
||||
SB_ACCUM(tn, (unsigned char)SE);
|
||||
tn->subpointer -= 2;
|
||||
SB_TERM(tn);
|
||||
suboption(conn); /* handle sub-option */
|
||||
telrcv_state = TS_DATA;
|
||||
tn->telrcv_state = TS_DATA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -988,7 +1014,12 @@ void telrcv(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;
|
||||
}
|
||||
|
||||
@@ -1003,8 +1034,13 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
||||
bool keepon = TRUE;
|
||||
char *buf = data->buffer;
|
||||
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);
|
||||
if(code)
|
||||
@@ -1060,9 +1096,9 @@ CURLcode Curl_telnet(struct connectdata *conn)
|
||||
/* Negotiate if the peer has started negotiating,
|
||||
otherwise don't. We don't want to speak telnet with
|
||||
non-telnet servers, like POP or SMTP. */
|
||||
if(please_negotiate && !already_negotiated) {
|
||||
if(tn->please_negotiate && !tn->already_negotiated) {
|
||||
negotiate(conn);
|
||||
already_negotiated = 1;
|
||||
tn->already_negotiated = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -89,6 +89,7 @@
|
||||
#include "getpass.h"
|
||||
#include "progress.h"
|
||||
#include "getdate.h"
|
||||
#include "http.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -337,6 +338,18 @@ _Transfer(struct connectdata *c_conn)
|
||||
return urg;
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
@@ -365,8 +378,10 @@ _Transfer(struct connectdata *c_conn)
|
||||
}
|
||||
/* check for Content-Length: header lines to get size */
|
||||
if (strnequal("Content-Length", p, 14) &&
|
||||
sscanf (p+14, ": %ld", &contentlength))
|
||||
sscanf (p+14, ": %ld", &contentlength)) {
|
||||
conn->size = contentlength;
|
||||
Curl_pgrsSetDownloadSize(data, contentlength);
|
||||
}
|
||||
else if (strnequal("Connection: close", p,
|
||||
strlen("Connection: close"))) {
|
||||
/*
|
||||
@@ -377,10 +392,25 @@ _Transfer(struct connectdata *c_conn)
|
||||
*/
|
||||
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)) {
|
||||
if (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
|
||||
obviously sends the header this way! :-( */
|
||||
if (data->resume_from == offset) {
|
||||
@@ -457,7 +487,7 @@ _Transfer(struct connectdata *c_conn)
|
||||
|
||||
if(0 == bodywrites) {
|
||||
/* 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) {
|
||||
/* HTTP-only checks */
|
||||
if (data->newurl) {
|
||||
@@ -514,6 +544,29 @@ _Transfer(struct connectdata *c_conn)
|
||||
} /* this is the first time we write a body part */
|
||||
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 &&
|
||||
(bytecount + nread >= conn->maxdownload)) {
|
||||
nread = conn->maxdownload - bytecount;
|
||||
@@ -526,9 +579,12 @@ _Transfer(struct connectdata *c_conn)
|
||||
|
||||
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);
|
||||
if(urg)
|
||||
return urg;
|
||||
}
|
||||
|
||||
} /* if (! header and data to read ) */
|
||||
} /* if( read from socket ) */
|
||||
@@ -625,8 +681,6 @@ _Transfer(struct connectdata *c_conn)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
typedef int (*func_T)(void);
|
||||
|
||||
CURLcode curl_transfer(CURL *curl)
|
||||
{
|
||||
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 */
|
||||
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 */
|
||||
memset(conn, 0, sizeof(struct connectdata));
|
||||
|
||||
@@ -994,6 +999,12 @@ static CURLcode _connect(CURL *curl,
|
||||
conn->secondarysocket = -1; /* no file descriptor */
|
||||
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
|
||||
* 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")) {
|
||||
conn->protocol |= PROT_FILE;
|
||||
|
||||
conn->curl_do = file;
|
||||
conn->curl_do = Curl_file;
|
||||
/* 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 */
|
||||
-1, NULL); /* no upload */
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
/* 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);
|
||||
}
|
||||
*in_connect = conn;
|
||||
|
||||
/*************************************************************
|
||||
* Resolve the name of the server or proxy
|
||||
@@ -1779,30 +1796,15 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect,
|
||||
if(CURLE_OK != code) {
|
||||
/* We're not allowed to return failure with memory left allocated
|
||||
in the connectdata struct, free those here */
|
||||
conn = (struct connectdata *)*in_connect;
|
||||
if(conn) {
|
||||
struct UrlData *data;
|
||||
int index;
|
||||
|
||||
conn = (struct connectdata *)*in_connect;
|
||||
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 */
|
||||
curl_disconnect(conn); /* close the connection */
|
||||
data->connects[index]=NULL; /* clear the pointer */
|
||||
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@@ -79,6 +79,8 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||
|
||||
/* Download buffer size, keep it fairly big for speed reasons */
|
||||
#define BUFSIZE (1024*50)
|
||||
|
||||
@@ -167,6 +169,8 @@ struct HTTP {
|
||||
struct Form form;
|
||||
size_t (*storefread)(char *, size_t , size_t , FILE *);
|
||||
FILE *in;
|
||||
|
||||
struct Curl_chunker chunk;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -183,12 +187,20 @@ struct FTP {
|
||||
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.
|
||||
*/
|
||||
struct ConnectBits {
|
||||
bool close; /* if set, we close the connection after this request */
|
||||
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 *https; /* alias, just for the sake of being more readable */
|
||||
struct FTP *ftp;
|
||||
#if 0 /* no need for special ones for these: */
|
||||
struct TELNET *telnet;
|
||||
struct FILE *file;
|
||||
void *telnet; /* private for telnet.c-eyes only */
|
||||
#if 0 /* no need for special ones for these: */
|
||||
struct LDAP *ldap;
|
||||
struct DICT *dict;
|
||||
#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
|
||||
# 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"`
|
||||
|
||||
|
@@ -1,3 +1,3 @@
|
||||
#define CURL_NAME "curl"
|
||||
#define CURL_VERSION "7.7-alpha2"
|
||||
#define CURL_VERSION "7.7-beta1"
|
||||
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
||||
|
32
tests/README
32
tests/README
@@ -7,7 +7,7 @@
|
||||
The cURL Test Suite
|
||||
|
||||
Requires:
|
||||
perl
|
||||
perl (and a unix-style shell)
|
||||
|
||||
Run:
|
||||
'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 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
|
||||
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
|
||||
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:
|
||||
All logs are generated in the logs/ subdirctory (it is emtpied first
|
||||
in the runtests.sh script)
|
||||
in the runtests.pl script)
|
||||
|
||||
Data:
|
||||
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.
|
||||
If the final result that curl should've got is not in this
|
||||
file, you can instead name the file replyN0001.txt. This enables
|
||||
you to fiddle more. ;-)
|
||||
file, you can instead name the file replyN0001.txt. This
|
||||
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
|
||||
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
|
||||
describe here!
|
||||
|
||||
FIX:
|
||||
TODO:
|
||||
|
||||
* 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 \
|
||||
command32.txt prot31.txt reply310001.txt reply320001.txt \
|
||||
name31.txt prot32.txt reply310002.txt reply320002.txt \
|
||||
command33.txt extra33.txt name33.txt prot33.txt reply33.txt
|
||||
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)
|
||||
Host: 127.0.0.1:8999
|
||||
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
|
||||
Pragma: no-cache
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE A
|
||||
LIST
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PORT 127,0,0,1,243,212
|
||||
TYPE A
|
||||
LIST
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE I
|
||||
RETR 102
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
CWD a/path
|
||||
PORT 127,0,0,1,246,33
|
||||
TYPE I
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
CWD a/path
|
||||
MDTM 103
|
||||
TYPE I
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER userdude
|
||||
PASS passfellow
|
||||
PWD
|
||||
PASV
|
||||
TYPE A
|
||||
RETR 103
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
CWD /path with spaces/and things2
|
||||
PASV
|
||||
TYPE A
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE I
|
||||
STOR 107
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
CWD CWD/STOR/RETR
|
||||
PORT 127,0,0,1,5,109
|
||||
TYPE I
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE I
|
||||
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
|
||||
Pragma: no-cache
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE I
|
||||
SIZE 110
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE I
|
||||
APPE 112
|
||||
|
@@ -1,4 +1,4 @@
|
||||
GET /want/12 HTTP/1.0
|
||||
GET /want/12 HTTP/1.1
|
||||
Range: bytes=100-200
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
PASV
|
||||
TYPE I
|
||||
RETR 106
|
||||
|
@@ -1,5 +1,6 @@
|
||||
USER anonymous
|
||||
PASS curl_by_daniel@haxx.se
|
||||
PWD
|
||||
DELE before_transfer
|
||||
PASV
|
||||
TYPE I
|
||||
|
@@ -1,4 +1,4 @@
|
||||
DELETE /want/13 HTTP/1.0
|
||||
DELETE /want/13 HTTP/1.1
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
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
|
||||
Host: 127.0.0.1:8999
|
||||
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
|
||||
Pragma: no-cache
|
||||
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=
|
||||
Host: we.want.that.site.com
|
||||
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
|
||||
Host: 127.0.0.1:8999
|
||||
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
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
|
@@ -1,4 +1,4 @@
|
||||
GET /2 HTTP/1.0
|
||||
GET /2 HTTP/1.1
|
||||
Authorization: Basic ZmFrZTp1c2Vy
|
||||
Host: 127.0.0.1:8999
|
||||
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)
|
||||
Host: 127.0.0.1:8999
|
||||
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)
|
||||
Host: 127.0.0.1:8999
|
||||
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
|
||||
Pragma: no-cache
|
||||
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-
|
||||
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
|
||||
Host: 127.0.0.1:8999
|
||||
|
@@ -1,4 +1,4 @@
|
||||
POST /3 HTTP/1.0
|
||||
POST /3 HTTP/1.1
|
||||
Authorization: Basic ZmFrZTotdXNlcg==
|
||||
Host: 127.0.0.1:8999
|
||||
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)
|
||||
Host: 127.0.0.1:8999
|
||||
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)
|
||||
Host: 127.0.0.1:8999
|
||||
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)
|
||||
Host: 127.0.0.1:8999
|
||||
Pragma: no-cache
|
||||
|
@@ -1,4 +1,4 @@
|
||||
PUT /33 HTTP/1.0
|
||||
PUT /33 HTTP/1.1
|
||||
Content-Range: bytes 50-149/150
|
||||
User-Agent: curl/7.6 (sparc-sun-solaris2.7) libcurl 7.6-pre4 (SSL 0.9.6) (krb4 enabled)
|
||||
Host: 127.0.0.1:8999
|
||||
|
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
|
||||
Pragma: no-cache
|
||||
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
|
||||
Pragma: no-cache
|
||||
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
|
||||
Host: 127.0.0.1:8999
|
||||
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
|
||||
Pragma: no-cache
|
||||
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
|
||||
Pragma: no-cache
|
||||
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
|
||||
Pragma: no-cache
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
|
||||
|
@@ -1,4 +1,5 @@
|
||||
HTTP/1.1 200 OK
|
||||
Server: thebest/1.0
|
||||
Connection: close
|
||||
|
||||
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
|
||||
Server: test-server/fake
|
||||
Location: data/110002.txt?coolsite=yes
|
||||
Connection: close
|
||||
|
||||
This server reply is for testing a simple Location: following
|
||||
|
@@ -350,6 +350,10 @@ for ( $waitedpid = 0;
|
||||
&customize(); # read test control instructions
|
||||
|
||||
print @welcome;
|
||||
if($verbose) {
|
||||
print STDERR "OUT:\n";
|
||||
print STDERR @welcome;
|
||||
}
|
||||
my $state="fresh";
|
||||
|
||||
while(1) {
|
||||
|
@@ -154,6 +154,10 @@ sub runftpserver {
|
||||
|
||||
if ($RUNNING != 1) {
|
||||
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 &");
|
||||
sleep 1; # give it a little time to start
|
||||
}
|
||||
|
Reference in New Issue
Block a user